Index: src/sas/qtgui/Perspectives/Inversion/InversionLogic.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/InversionLogic.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/InversionLogic.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,91 @@
+import numpy as np
+
+from sas.qtgui.Plotting.PlotterData import Data1D
+
+
+class InversionLogic(object):
+    """
+    All the data-related logic. This class deals exclusively with Data1D/2D
+    No QStandardModelIndex here.
+    """
+
+    def __init__(self, data=None):
+        self._data = data
+        self.data_is_loaded = False
+        if data is not None:
+            self.data_is_loaded = True
+
+    @property
+    def data(self):
+        return self._data
+
+    @data.setter
+    def data(self, value):
+        """ data setter """
+        self._data = value
+        self.data_is_loaded = True
+
+    def isLoadedData(self):
+        """ accessor """
+        return self.data_is_loaded
+
+    def new1DPlot(self, return_data):
+        """
+        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
+
+        # Create the new plot
+        new_plot = Data1D(x=x, y=y)
+        new_plot.is_data = False
+        new_plot.dy = np.zeros(len(y))
+        _yaxis, _yunit = data.get_yaxis()
+        _xaxis, _xunit = data.get_xaxis()
+
+        new_plot.group_id = data.group_id
+        new_plot.id = data.name
+        new_plot.name = model.name + " [" + data.name + "]"
+        new_plot.title = new_plot.name
+        new_plot.xaxis(_xaxis, _xunit)
+        new_plot.yaxis(_yaxis, _yunit)
+
+        return new_plot
+
+    def computeDataRange(self):
+        """
+        Wrapper for calculating the data range based on local dataset
+        """
+        return self.computeRangeFromData(self.data)
+
+    def computeRangeFromData(self, data):
+        """
+        Compute the minimum and the maximum range of the data
+        return the npts contains in data
+        """
+        qmin, qmax, npts = None, None, None
+        if isinstance(data, Data1D):
+            try:
+                qmin = min(data.x)
+                qmax = max(data.x)
+                npts = len(data.x)
+            except (ValueError, TypeError):
+                msg = "Unable to find min/max/length of \n data named %s" % \
+                            self.data.filename
+                raise ValueError, msg
+
+        else:
+            qmin = 0
+            try:
+                x = max(np.fabs(data.xmin), np.fabs(data.xmax))
+                y = max(np.fabs(data.ymin), np.fabs(data.ymax))
+            except (ValueError, TypeError):
+                msg = "Unable to find min/max of \n data named %s" % \
+                            self.data.filename
+                raise ValueError, msg
+            qmax = np.sqrt(x * x + y * y)
+            npts = len(data.data)
+        return qmin, qmax, npts
Index: src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,548 @@
+import sys
+import logging
+import pylab
+import numpy as np
+
+from PyQt4 import QtGui, QtCore, QtWebKit
+from twisted.internet import reactor
+
+# sas-global
+import sas.qtgui.Utilities.GuiUtils as GuiUtils
+
+# pr inversion GUI elements
+from InversionUtils import WIDGETS
+import UI.TabbedPrInversionUI
+from UI.TabbedPrInversionUI import Ui_PrInversion
+from InversionLogic import InversionLogic
+
+# pr inversion calculation elements
+from sas.sascalc.dataloader.data_info import Data1D
+from sas.sascalc.pr.invertor import Invertor
+
+def is_float(value):
+    try:
+        return float(value)
+    except ValueError:
+        return 0.0
+
+class InversionWindow(QtGui.QTabWidget, Ui_PrInversion):
+    """
+    The main window for the P(r) Inversion perspective.
+    """
+
+    name = "Inversion"
+
+    def __init__(self, parent=None, data=None):
+        super(InversionWindow, self).__init__()
+        self.setupUi(self)
+
+        self.setWindowTitle("P(r) Inversion Perspective")
+
+        self._manager = parent
+        self._model_item = QtGui.QStandardItem()
+        self._helpView = QtWebKit.QWebView()
+
+        self.communicate = GuiUtils.Communicate()
+
+        self.logic = InversionLogic()
+
+        # The window should not close
+        self._allow_close = False
+
+        # current QStandardItem showing on the panel
+        self._data = None
+        # current Data1D as referenced by self._data
+        self._data_set = None
+
+        # p(r) calculator
+        self._calculator = Invertor()
+        self._last_calculator = None
+        self.calc_thread = None
+        self.estimation_thread = None
+
+        # Current data object in view
+        self._data_index = 0
+        # list mapping data to p(r) calculation
+        self._data_list = []
+        if not isinstance(data, list):
+            data = [data]
+        for datum in data:
+            self._data_list.append({datum: self._calculator.clone()})
+
+        # plots
+        self.pr_plot = None
+        self.data_plot = None
+
+        self.model = QtGui.QStandardItemModel(self)
+        self.mapper = QtGui.QDataWidgetMapper(self)
+        # Link user interactions with methods
+        self.setupLinks()
+        # Set values
+        self.setupModel()
+        # Set up the Widget Map
+        self.setupMapper()
+
+    ######################################################################
+    # Base Perspective Class Definitions
+
+    def communicator(self):
+        return self.communicate
+
+    def allowBatch(self):
+        return False
+
+    def setClosable(self, value=True):
+        """
+        Allow outsiders close this widget
+        """
+        assert isinstance(value, bool)
+        self._allow_close = value
+
+    def closeEvent(self, event):
+        """
+        Overwrite QDialog close method to allow for custom widget close
+        """
+        if self._allow_close:
+            # reset the closability flag
+            self.setClosable(value=False)
+            event.accept()
+        else:
+            event.ignore()
+            # Maybe we should just minimize
+            self.setWindowState(QtCore.Qt.WindowMinimized)
+
+    ######################################################################
+    # Initialization routines
+
+    def setupLinks(self):
+        """Connect the use controls to their appropriate methods"""
+        self.enableButtons()
+        self.checkBgdClicked(False)
+        # TODO: enable the drop down box once batch is working
+        self.dataList.setEnabled(False)
+        # TODO: enable displayChange once batch is working
+        # self.dataList.currentIndexChanged.connect(self.displayChange)
+        self.calculateButton.clicked.connect(self._calculation)
+        self.helpButton.clicked.connect(self.help)
+        self.estimateBgd.toggled.connect(self.toggleBgd)
+        self.manualBgd.toggled.connect(self.toggleBgd)
+        self.regConstantSuggestionButton.clicked.connect(self.acceptAlpha)
+        self.noOfTermsSuggestionButton.clicked.connect(self.acceptNoTerms)
+        self.explorerButton.clicked.connect(self.openExplorerWindow)
+        self.model.itemChanged.connect(self.model_changed)
+
+    def setupMapper(self):
+        # Set up the mapper.
+        self.mapper.setOrientation(QtCore.Qt.Vertical)
+        self.mapper.setModel(self.model)
+
+        # Filename
+        self.mapper.addMapping(self.dataList, WIDGETS.W_FILENAME)
+        # Background
+        self.mapper.addMapping(self.backgroundInput, WIDGETS.W_BACKGROUND_INPUT)
+        self.mapper.addMapping(self.estimateBgd, WIDGETS.W_ESTIMATE)
+        self.mapper.addMapping(self.manualBgd, WIDGETS.W_MANUAL_INPUT)
+
+        # Qmin/Qmax
+        self.mapper.addMapping(self.minQInput, WIDGETS.W_QMIN)
+        self.mapper.addMapping(self.maxQInput, WIDGETS.W_QMAX)
+
+        # Slit Parameter items
+        self.mapper.addMapping(self.slitWidthInput, WIDGETS.W_SLIT_WIDTH)
+        self.mapper.addMapping(self.slitHeightInput, WIDGETS.W_SLIT_HEIGHT)
+
+        # Parameter Items
+        self.mapper.addMapping(self.regularizationConstantInput,
+                               WIDGETS.W_REGULARIZATION)
+        self.mapper.addMapping(self.regConstantSuggestionButton,
+                               WIDGETS.W_REGULARIZATION_SUGGEST)
+        self.mapper.addMapping(self.explorerButton, WIDGETS.W_EXPLORE)
+        self.mapper.addMapping(self.maxDistanceInput, WIDGETS.W_MAX_DIST)
+        self.mapper.addMapping(self.noOfTermsInput, WIDGETS.W_NO_TERMS)
+        self.mapper.addMapping(self.noOfTermsSuggestionButton,
+                               WIDGETS.W_NO_TERMS_SUGGEST)
+
+        # Output
+        self.mapper.addMapping(self.rgValue, WIDGETS.W_RG)
+        self.mapper.addMapping(self.iQ0Value, WIDGETS.W_I_ZERO)
+        self.mapper.addMapping(self.backgroundValue, WIDGETS.W_BACKGROUND_OUTPUT)
+        self.mapper.addMapping(self.computationTimeValue, WIDGETS.W_COMP_TIME)
+        self.mapper.addMapping(self.chiDofValue, WIDGETS.W_CHI_SQUARED)
+        self.mapper.addMapping(self.oscillationValue, WIDGETS.W_OSCILLATION)
+        self.mapper.addMapping(self.posFractionValue, WIDGETS.W_POS_FRACTION)
+        self.mapper.addMapping(self.sigmaPosFractionValue,
+                               WIDGETS.W_SIGMA_POS_FRACTION)
+
+        # Main Buttons
+        self.mapper.addMapping(self.calculateButton, WIDGETS.W_CALCULATE)
+        self.mapper.addMapping(self.helpButton, WIDGETS.W_HELP)
+
+        self.mapper.toFirst()
+
+    def setupModel(self):
+        """
+        Update boxes with initial values
+        """
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_FILENAME, item)
+        item = QtGui.QStandardItem('0.0')
+        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_QMIN, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_QMAX, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_SLIT_WIDTH, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_SLIT_HEIGHT, item)
+        item = QtGui.QStandardItem("10")
+        self.model.setItem(WIDGETS.W_NO_TERMS, item)
+        item = QtGui.QStandardItem("0.0001")
+        self.model.setItem(WIDGETS.W_REGULARIZATION, item)
+        item = QtGui.QStandardItem("140.0")
+        self.model.setItem(WIDGETS.W_MAX_DIST, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_RG, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_I_ZERO, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_COMP_TIME, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_CHI_SQUARED, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_OSCILLATION, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_POS_FRACTION, item)
+        item = QtGui.QStandardItem("")
+        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION, item)
+
+    ######################################################################
+    # Methods for updating GUI
+
+    def enableButtons(self):
+        """
+        Enable buttons when data is present, else disable them
+        """
+        if self.logic.data_is_loaded:
+            self.explorerButton.setEnabled(True)
+            self.calculateButton.setEnabled(True)
+        else:
+            self.calculateButton.setEnabled(False)
+            self.explorerButton.setEnabled(False)
+
+    def populateDataComboBox(self, filename):
+        """
+        Append a new file name to the data combobox
+        :param data: Data1D object
+        """
+        qt_item = QtCore.QString.fromUtf8(filename)
+        self.dataList.addItem(qt_item)
+
+    def acceptNoTerms(self):
+        """Send estimated no of terms to input"""
+        self.model.setItem(WIDGETS.W_NO_TERMS, QtGui.QStandardItem(
+            self.noOfTermsSuggestionButton.text()))
+
+    def acceptAlpha(self):
+        """Send estimated alpha to input"""
+        self.model.setItem(WIDGETS.W_REGULARIZATION, QtGui.QStandardItem(
+            self.regConstantSuggestionButton.text()))
+
+    ######################################################################
+    # GUI Interaction Events
+
+    def update_calculator(self):
+        """Update all p(r) params. Take all GUI values as an override"""
+        self._calculator.set_x(self._data_set.x)
+        self._calculator.set_y(self._data_set.y)
+        self._calculator.set_err(self._data_set.dy)
+        self._calculator.set_qmin(is_float(UI.TabbedPrInversionUI._fromUtf8(
+            self.minQInput.text())))
+        self._calculator.set_qmax(is_float(UI.TabbedPrInversionUI._fromUtf8(
+            self.maxQInput.text())))
+        self._calculator.set_alpha(is_float(UI.TabbedPrInversionUI._fromUtf8(
+            self.regularizationConstantInput.text())))
+        self._calculator.set_dmax(is_float(UI.TabbedPrInversionUI._fromUtf8(
+            self.maxDistanceInput.text())))
+        self._calculator.set_est_bck(int(is_float(
+            UI.TabbedPrInversionUI._fromUtf8(self.backgroundInput.text()))))
+        self._calculator.set_slit_height(is_float(
+            UI.TabbedPrInversionUI._fromUtf8(self.slitHeightInput.text())))
+        self._calculator.set_slit_width(is_float(
+            UI.TabbedPrInversionUI._fromUtf8(self.slitWidthInput.text())))
+
+    def _calculation(self):
+        """
+        Calculate the P(r) for every data set in the data list
+        """
+        # Pull in any GUI changes before running the calculations
+        self.update_calculator()
+        # Run
+        self.startThread()
+
+    def model_changed(self):
+        """Update the values when user makes changes"""
+        if not self.mapper:
+            return
+        # TODO: Update plots
+        self.mapper.toFirst()
+
+    def help(self):
+        """
+        Open the P(r) Inversion help browser
+        """
+        tree_location = (GuiUtils.HELP_DIRECTORY_LOCATION +
+                         "user/sasgui/perspectives/pr/pr_help.html")
+
+        # Actual file anchor will depend on the combo box index
+        # Note that we can be clusmy here, since bad current_fitter_id
+        # will just make the page displayed from the top
+        self._helpView.load(QtCore.QUrl(tree_location))
+        self._helpView.show()
+
+    def checkBgdClicked(self, boolean=None):
+        if boolean or self.manualBgd.isChecked():
+            self.manualBgd.setChecked(True)
+            self.toggleBgd(self.manualBgd)
+        else:
+            self.estimateBgd.setChecked(True)
+            self.toggleBgd(self.estimateBgd)
+
+    def toggleBgd(self, item=None):
+        """
+        Toggle the background between manual and estimated
+        :param item: gui item that was triggered
+        """
+        if not item:
+            self.checkBgdClicked()
+        elif isinstance(item, QtGui.QRadioButton):
+            if item is self.estimateBgd:
+                self.backgroundInput.setEnabled(False)
+            else:
+                self.backgroundInput.setEnabled(True)
+
+    def openExplorerWindow(self):
+        """
+        Open the Explorer window to see correlations between params and results
+        """
+        # TODO: This depends on SVCC-45
+        pass
+
+    ######################################################################
+    # Response Actions
+
+    def setData(self, data_item=None, is_batch=False):
+        """
+        Assign new data set or sets to the P(r) perspective
+        Obtain a QStandardItem object and dissect it to get Data1D/2D
+        Pass it over to the calculator
+        """
+        assert data_item is not None
+
+        if not isinstance(data_item, list):
+            msg = "Incorrect type passed to the P(r) Perspective"
+            raise AttributeError, msg
+
+        if not isinstance(data_item[0], QtGui.QStandardItem):
+            msg = "Incorrect type passed to the P(r) Perspective"
+            raise AttributeError, msg
+
+        for data in data_item:
+            self._data = data
+            self._data_set = GuiUtils.dataFromItem(data)
+            self.enableButtons()
+            self.populateDataComboBox(self._data_set.filename)
+
+            # Estimate initial values from data
+            self.performEstimate()
+            self.logic.data(self._calculator)
+
+            self._manager.createGuiData(None)
+
+            # TODO: Finish plotting
+            if self.pr_plot is None:
+                self.pr_plot = None
+                #self.pr_plot = self.logic.new1DPlot(self._calculator)
+            if self.data_plot is None:
+                self.data_plot = None
+
+            qmin, qmax, _ = self.logic.computeDataRange()
+            title = self._data.filename
+
+            self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem(
+                "{:.4g}".format(qmin)))
+            self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem(
+                "{:.4g}".format(qmax)))
+            #reactor.callFromThread(GuiUtils.updateModelItemWithPlot,
+            #                       self._model_item, self._communicator, title)
+
+            # TODO: Only load 1st data until batch mode working. Thus, break
+            break
+
+    ######################################################################
+    # Thread Creators
+
+    def startThread(self):
+        """
+            Start a calculation thread
+        """
+        from Thread import CalcPr
+
+        # If a thread is already started, stop it
+        if self.calc_thread is not None and self.calc_thread.isrunning():
+            self.calc_thread.stop()
+        pr = self._calculator.clone()
+        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
+            self.noOfTermsInput.text()))
+        self.calc_thread = CalcPr(pr, nfunc,
+                                  error_func=self._threadError,
+                                  completefn=self._completed, updatefn=None)
+        self.calc_thread.queue()
+        self.calc_thread.ready(2.5)
+
+    def performEstimateNT(self):
+        """
+            Perform parameter estimation
+        """
+        from Thread import EstimateNT
+
+        # If a thread is already started, stop it
+        if (self.estimation_thread is not None and
+                self.estimation_thread.isrunning()):
+            self.estimation_thread.stop()
+        pr = self._calculator.clone()
+        # Skip the slit settings for the estimation
+        # It slows down the application and it doesn't change the estimates
+        pr.slit_height = 0.0
+        pr.slit_width = 0.0
+        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
+            self.noOfTermsInput.text()))
+        self.estimation_thread = EstimateNT(pr, nfunc,
+                                            error_func=self._threadError,
+                                            completefn=self._estimateNTCompleted,
+                                            updatefn=None)
+        self.estimation_thread.queue()
+        self.estimation_thread.ready(2.5)
+
+    def performEstimate(self):
+        """
+            Perform parameter estimation
+        """
+        from Thread import EstimatePr
+
+        self._calculation()
+
+        # If a thread is already started, stop it
+        if (self.estimation_thread is not None and
+                self.estimation_thread.isrunning()):
+            self.estimation_thread.stop()
+        pr = self._calculator.clone()
+        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
+            self.noOfTermsInput.text()))
+        self.estimation_thread = EstimatePr(pr, nfunc,
+                                            error_func=self._threadError,
+                                            completefn=self._estimateCompleted,
+                                            updatefn=None)
+        self.estimation_thread.queue()
+        self.estimation_thread.ready(2.5)
+
+    ######################################################################
+    # Thread Complete
+
+    def _estimateCompleted(self, alpha, message, elapsed):
+        """
+        Parameter estimation completed,
+        display the results to the user
+
+        :param alpha: estimated best alpha
+        :param elapsed: computation time
+        """
+        # Save useful info
+        self.model.setItem(WIDGETS.W_COMP_TIME,
+                           QtGui.QStandardItem(str(elapsed)))
+        self.regConstantSuggestionButton.setText(QtCore.QString(str(alpha)))
+        self.regConstantSuggestionButton.setEnabled(True)
+        if message:
+            logging.info(message)
+        self.performEstimateNT()
+
+    def _estimateNTCompleted(self, nterms, alpha, message, elapsed):
+        """
+        Parameter estimation completed,
+        display the results to the user
+
+        :param alpha: estimated best alpha
+        :param nterms: estimated number of terms
+        :param elapsed: computation time
+
+        """
+        # Save useful info
+        self.noOfTermsSuggestionButton.setText(QtCore.QString(
+            "{:n}".format(nterms)))
+        self.noOfTermsSuggestionButton.setEnabled(True)
+        self.regConstantSuggestionButton.setText(QtCore.QString(
+            "{:.3g}".format(alpha)))
+        self.regConstantSuggestionButton.setEnabled(True)
+        self.model.setItem(WIDGETS.W_COMP_TIME,
+                           QtGui.QStandardItem(str(elapsed)))
+        self.PrTabWidget.setCurrentIndex(0)
+        if message:
+            logging.info(message)
+
+    def _completed(self, out, cov, pr, elapsed):
+        """
+        Method called with the results when the inversion is done
+
+        :param out: output coefficient for the base functions
+        :param cov: covariance matrix
+        :param pr: Invertor instance
+        :param elapsed: time spent computing
+
+        """
+        # Save useful info
+        # Keep a copy of the last result
+        self._last_calculator = pr.clone()
+
+        # Save Pr invertor
+        self._calculator = pr
+        cov = np.ascontiguousarray(cov)
+
+        # Show result on control panel
+
+        # TODO: Connect self._calculator to GUI
+        self.model.setItem(WIDGETS.W_RG, QtGui.QStandardItem(str(pr.rg(out))))
+        self.model.setItem(WIDGETS.W_I_ZERO,
+                           QtGui.QStandardItem(str(pr.iq0(out))))
+        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT,
+                           QtGui.QStandardItem("{:.3f}".format(pr.background)))
+        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT,
+                           QtGui.QStandardItem(str(pr.background)))
+        self.model.setItem(WIDGETS.W_CHI_SQUARED,
+                           QtGui.QStandardItem(str(pr.chi2[0])))
+        self.model.setItem(WIDGETS.W_COMP_TIME,
+                           QtGui.QStandardItem(str(elapsed)))
+        self.model.setItem(WIDGETS.W_OSCILLATION,
+                           QtGui.QStandardItem(str(pr.oscillations(out))))
+        self.model.setItem(WIDGETS.W_POS_FRACTION,
+                           QtGui.QStandardItem(str(pr.get_positive(out))))
+        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION,
+                           QtGui.QStandardItem(str(pr.get_pos_err(out, cov))))
+
+        # Display results tab
+        self.PrTabWidget.setCurrentIndex(1)
+        self._data_list.append({self._data: pr})
+
+        # TODO: Show plots - Really, this should be linked to the inputs, etc,
+        # TODO: so it should happen automagically
+        # Show I(q) fit
+        # self.show_iq(out, self._calculator)
+        # Show P(r) fit
+        # self.show_pr(out, self._calculator, cov)
+
+    def _threadError(self, error):
+        """
+            Call-back method for calculation errors
+        """
+        logging.warning(error)
Index: src/sas/qtgui/Perspectives/Inversion/InversionUtils.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/InversionUtils.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/InversionUtils.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,31 @@
+def enum(*sequential, **named):
+    enums = dict(zip(sequential, range(len(sequential))), **named)
+    return type('Enum', (), enums)
+
+WIDGETS = enum( 'W_FILENAME',               #0
+                'W_BACKGROUND_INPUT',             #1
+                'W_ESTIMATE',               #2
+                'W_MANUAL_INPUT',           #3
+                'W_QMIN',                   #4
+                'W_QMAX',                   #5
+                'W_SLIT_HEIGHT',            #6
+                'W_SLIT_WIDTH',             #7
+                'W_NO_TERMS',               #8
+                'W_NO_TERMS_SUGGEST',       #9
+                'W_REGULARIZATION',         #10
+                'W_REGULARIZATION_SUGGEST', #11
+                'W_MAX_DIST',               #12
+                'W_EXPLORE',                #13
+                # results
+                'W_RG',
+                'W_I_ZERO',
+                'W_BACKGROUND_OUTPUT',
+                'W_COMP_TIME',
+                'W_CHI_SQUARED',
+                'W_OSCILLATION',
+                'W_POS_FRACTION',
+                'W_SIGMA_POS_FRACTION',
+                # bottom buttons
+                'W_CALCULATE',
+                'W_HELP'
+)
Index: src/sas/qtgui/Perspectives/Inversion/Thread.py
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/Thread.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/Thread.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,104 @@
+import sys
+import time
+from sas.sascalc.data_util.calcthread import CalcThread
+
+
+class CalcPr(CalcThread):
+    """
+    Compute P(r)
+    """
+
+    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
+                 updatefn=None, yieldtime=0.01, worktime=0.01):
+        """
+        """
+        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
+        self.pr = pr
+        self.nfunc = nfunc
+        self.error_func = error_func
+        self.starttime = 0
+
+    def compute(self):
+        """
+        Perform P(r) inversion
+        """
+        try:
+            self.starttime = time.time()
+            out, cov = self.pr.invert(self.nfunc)
+            elapsed = time.time() - self.starttime
+            self.complete(out=out, cov=cov, pr=self.pr, elapsed=elapsed)
+        except KeyboardInterrupt:
+            # Thread was interrupted, just proceed
+            pass
+        except:
+            if self.error_func is not None:
+                self.error_func("CalcPr.compute: %s" % sys.exc_value)
+
+
+class EstimatePr(CalcThread):
+    """
+    Estimate P(r)
+    """
+
+    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
+                 updatefn=None, yieldtime=0.01, worktime=0.01):
+        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
+        self.pr = pr
+        self.nfunc = nfunc
+        self.error_func = error_func
+        self.starttime = 0
+
+    def compute(self):
+        """
+        Calculates the estimate
+        """
+        try:
+            alpha, message, elapsed = self.pr.estimate_alpha(self.nfunc)
+            self.isquit()
+            self.complete(alpha=alpha, message=message, elapsed=elapsed)
+        except KeyboardInterrupt:
+            # Thread was interrupted, just proceed
+            pass
+        except:
+            if self.error_func is not None:
+                self.error_func("EstimatePr.compute: %s" % sys.exc_value)
+
+
+class EstimateNT(CalcThread):
+    """
+    """
+    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
+                 updatefn=None, yieldtime=0.01, worktime=0.01):
+        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
+        self.pr = pr
+        self.nfunc = nfunc
+        self.error_func = error_func
+        self.starttime = 0
+        self._time_for_sleep = 0
+        self._sleep_delay = 1.0
+
+    def isquit(self):
+        """
+        """
+        CalcThread.isquit(self)
+        if time.time() > self._time_for_sleep + self._sleep_delay:
+            time.sleep(.2)
+            self._time_for_sleep = time.time()
+
+    def compute(self):
+        """
+        Calculates the estimate
+        """
+        try:
+            t_0 = time.time()
+            self._time_for_sleep = t_0
+            nterms, alpha, message = self.pr.estimate_numterms(self.isquit)
+            t_1 = time.time() - t_0
+            self.isquit()
+            self.complete(nterms=nterms, alpha=alpha, message=message, elapsed=t_1)
+        except KeyboardInterrupt:
+            # Thread was interrupted, just proceed
+            pass
+        except:
+            if self.error_func is not None:
+                self.error_func("EstimatePr2.compute: %s" % sys.exc_value)
Index: src/sas/qtgui/Perspectives/Inversion/UI/TabbedPrInversionUI.ui
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/UI/TabbedPrInversionUI.ui	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/UI/TabbedPrInversionUI.ui	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PrInversion</class>
+ <widget class="QDialog" name="PrInversion">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>458</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>458</width>
+    <height>500</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>458</width>
+    <height>500</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>P(r) Inversion</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_7">
+   <item row="3" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout_8">
+     <property name="sizeConstraint">
+      <enum>QLayout::SetDefaultConstraint</enum>
+     </property>
+     <item>
+      <widget class="QPushButton" name="calculateButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Calculate</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="helpButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Help</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>2</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="0">
+    <widget class="QTabWidget" name="PrTabWidget">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tabMain">
+      <attribute name="title">
+       <string>P(r) Parameters</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_6" stretch="0,1,1,0">
+       <item>
+        <widget class="QGroupBox" name="dataSourceGroupBox">
+         <property name="title">
+          <string>I(q) data source</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="1" column="0">
+           <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="2,1,0,2,2">
+            <item>
+             <widget class="QLabel" name="label_5">
+              <property name="text">
+               <string>Background Level:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="backgroundInput">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>0.0</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_10">
+              <property name="text">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
+&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="estimateBgd">
+              <property name="text">
+               <string>Estimate</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="manualBgd">
+              <property name="text">
+               <string>Manual Input</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="0" column="0">
+           <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,3">
+            <item>
+             <widget class="QLabel" name="label">
+              <property name="text">
+               <string>Data File Name:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="dataList"/>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="qRangeGroupBox">
+         <property name="title">
+          <string>Total Q range</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_3">
+          <item row="0" column="0">
+           <layout class="QHBoxLayout" name="horizontalLayout_4">
+            <item>
+             <widget class="QLabel" name="label_7">
+              <property name="text">
+               <string>Min:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="minQInput">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_11">
+              <property name="text">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
+&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_8">
+              <property name="text">
+               <string>Max:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="maxQInput">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_9">
+              <property name="text">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
+&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="slitParamsGroupBox">
+         <property name="title">
+          <string>Slit Parameters</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout">
+          <item row="0" column="0">
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QLabel" name="label_3">
+              <property name="text">
+               <string>Height</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="slitHeightInput">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_6">
+              <property name="text">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
+&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_4">
+              <property name="text">
+               <string>Width</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="slitWidthInput">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="label_2">
+              <property name="text">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
+&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="paramGroupBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="toolTip">
+          <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&gt;&lt;span style=&quot; font-family:'Courier New'; font-size:9pt; color:#000000;&quot;&gt;P(r) is found by fitting a set of base functions to I(Q). The minimization involves a regularization term to ensure a smooth P(r). The regularization constant gives the size of that term. The suggested value is the value above which the output P(r) will have only one peak.&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         </property>
+         <property name="title">
+          <string>Parameters</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_8">
+          <item row="1" column="0">
+           <widget class="QLabel" name="label_13">
+            <property name="text">
+             <string>Regularization constant</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QPushButton" name="noOfTermsSuggestionButton">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2">
+           <widget class="QPushButton" name="explorerButton">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open the D&lt;span style=&quot; vertical-align:sub;&quot;&gt;max&lt;/span&gt; explorer window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="layoutDirection">
+             <enum>Qt::LeftToRight</enum>
+            </property>
+            <property name="text">
+             <string>Explore</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="noOfTermsInput"/>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="maxDistanceInput"/>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_12">
+            <property name="text">
+             <string>Number of Terms</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QPushButton" name="regConstantSuggestionButton">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="label_14">
+            <property name="text">
+             <string>Max distance [Ã
+]</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLineEdit" name="regularizationConstantInput"/>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tabOptions">
+      <attribute name="title">
+       <string>Outputs</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_6">
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="outputsGroupBox">
+         <property name="title">
+          <string>Outputs</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="0" column="1">
+           <widget class="QLabel" name="label_23">
+            <property name="text">
+             <string>Calculated Value</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignCenter</set>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QLabel" name="label_28">
+            <property name="text">
+             <string>Units</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="1">
+           <widget class="QLineEdit" name="oscillationValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QLabel" name="label_17">
+            <property name="text">
+             <string>Background</string>
+            </property>
+           </widget>
+          </item>
+          <item row="7" column="1">
+           <widget class="QLineEdit" name="posFractionValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2">
+           <widget class="QLabel" name="label_25">
+            <property name="text">
+             <string>Ã
+-1</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1">
+           <widget class="QLineEdit" name="backgroundValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="label_15">
+            <property name="text">
+             <string>Rg</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QLabel" name="label_24">
+            <property name="text">
+             <string>Ã
+</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0">
+           <widget class="QLabel" name="label_20">
+            <property name="text">
+             <string>Oscillations</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0">
+           <widget class="QLabel" name="label_18">
+            <property name="text">
+             <string>Computation Time</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="2">
+           <widget class="QLabel" name="label_27">
+            <property name="text">
+             <string>secs</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="label_16">
+            <property name="text">
+             <string>I(Q=0)</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="2">
+           <widget class="QLabel" name="label_26">
+            <property name="text">
+             <string>Ã
+-1</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_22">
+            <property name="text">
+             <string>Parameter</string>
+            </property>
+           </widget>
+          </item>
+          <item row="8" column="0">
+           <widget class="QLabel" name="label_29">
+            <property name="text">
+             <string>1-sigma positive fraction</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="iQ0Value">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0">
+           <widget class="QLabel" name="label_19">
+            <property name="text">
+             <string>Chi^2/dof</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLineEdit" name="rgValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="1">
+           <widget class="QLineEdit" name="chiDofValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="1">
+           <widget class="QLineEdit" name="computationTimeValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="7" column="0">
+           <widget class="QLabel" name="label_21">
+            <property name="text">
+             <string>Positive Fraction</string>
+            </property>
+           </widget>
+          </item>
+          <item row="8" column="1">
+           <widget class="QLineEdit" name="sigmaPosFractionValue">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: src/sas/qtgui/Perspectives/Inversion/UI/convert_all.bat
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/UI/convert_all.bat	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/UI/convert_all.bat	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,7 @@
+@echo off
+
+for %%f in (*.ui) do (
+  call pyuic4.bat %%f > %%~nf.py
+)
+
+
Index: src/sas/qtgui/Perspectives/Inversion/UI/convert_all.sh
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/UI/convert_all.sh	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/UI/convert_all.sh	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,6 @@
+# UI -> PY
+for filename in *.ui; do
+  pyuic4 $filename > "`basename "$filename" .ui`.py"
+done
+
+
Index: src/sas/qtgui/Perspectives/Inversion/UI/convert_ui.sh
===================================================================
--- src/sas/qtgui/Perspectives/Inversion/UI/convert_ui.sh	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
+++ src/sas/qtgui/Perspectives/Inversion/UI/convert_ui.sh	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -0,0 +1,1 @@
+pyuic.bat -w $1.ui > $1.py
Index: src/sas/qtgui/Perspectives/PrInversion/PrInversionPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/PrInversionPerspective.py	(revision d1a479379dc4b0df1a084a19ca1057f2e23dc0e7)
+++ 	(revision )
@@ -1,556 +1,0 @@
-import sys
-import logging
-import pylab
-import numpy as np
-
-from PyQt4 import QtGui, QtCore, QtWebKit
-
-# sas-global
-import sas.qtgui.Utilities.GuiUtils as GuiUtils
-
-# pr inversion gui elements
-from PrInversionUtils import WIDGETS
-import UI.TabbedPrInversionUI
-from UI.TabbedPrInversionUI import Ui_PrInversion
-
-# pr inversion calculation elements
-from sas.sascalc.dataloader.data_info import Data1D
-from sas.sascalc.pr.invertor import Invertor
-
-def is_float(value):
-    try:
-        return float(value)
-    except ValueError:
-        return 0.0
-
-class PrInversionWindow(QtGui.QTabWidget, Ui_PrInversion):
-    """
-    The main window for the P(r) Inversion perspective.
-    """
-
-    name = "PrInversion"
-
-    def __init__(self, parent=None, data=None):
-        super(PrInversionWindow, self).__init__()
-        self.setupUi(self)
-
-        self.setWindowTitle("P(r) Inversion Perspective")
-
-        self._manager = parent
-        self._model_item = QtGui.QStandardItem()
-        self._helpView = QtWebKit.QWebView()
-
-        self.communicate = GuiUtils.Communicate()
-
-        # The window should not close
-        self._allow_close = False
-
-        # is there data
-        self._has_data = False
-        self._data = Data1D()
-
-        # p(r) calculator
-        self._calculator = Invertor()
-        self._last_calculator = None
-        self.calc_thread = None
-        self.estimation_thread = None
-
-        # Current data object in view
-        self._data_index = 0
-        # list mapping data to p(r) calculation
-        self._data_list = []
-        if not isinstance(data, list):
-            data = [data]
-        for datum in data:
-            self._data_list.append({datum: self._calculator.clone()})
-
-        self.model = QtGui.QStandardItemModel(self)
-        self.mapper = QtGui.QDataWidgetMapper(self)
-        # Link user interactions with methods
-        self.setupLinks()
-        # Set values
-        self.setupModel()
-        # Set up the Widget Map
-        self.setupMapper()
-
-    ######################################################################
-    # Base Perspective Class Definitions
-
-    def allowBatch(self):
-        return False
-
-    def setClosable(self, value=True):
-        """
-        Allow outsiders close this widget
-        """
-        assert isinstance(value, bool)
-        self._allow_close = value
-
-    def closeEvent(self, event):
-        """
-        Overwrite QDialog close method to allow for custom widget close
-        """
-        if self._allow_close:
-            # reset the closability flag
-            self.setClosable(value=False)
-            event.accept()
-        else:
-            event.ignore()
-            # Maybe we should just minimize
-            self.setWindowState(QtCore.Qt.WindowMinimized)
-
-    ######################################################################
-    # Initialization routines
-
-    def setupLinks(self):
-        """Connect the use controls to their appropriate methods"""
-        self.enableButtons()
-        self.checkBgdClicked(False)
-        # TODO: enable the drop down box once batch is working
-        self.dataList.setEnabled(False)
-        # TODO: enable displayChange once batch is working
-        # self.dataList.currentIndexChanged.connect(self.displayChange)
-        self.calculateButton.clicked.connect(self._calculation)
-        self.helpButton.clicked.connect(self.help)
-        self.estimateBgd.toggled.connect(self.toggleBgd)
-        self.manualBgd.toggled.connect(self.toggleBgd)
-        self.regConstantSuggestionButton.clicked.connect(self.acceptAlpha)
-        self.noOfTermsSuggestionButton.clicked.connect(self.acceptNoTerms)
-        self.explorerButton.clicked.connect(self.openExplorerWindow)
-        self.model.itemChanged.connect(self.model_changed)
-
-    def setupMapper(self):
-        # Set up the mapper.
-        self.mapper.setOrientation(QtCore.Qt.Vertical)
-        self.mapper.setModel(self.model)
-
-        # Filename
-        self.mapper.addMapping(self.dataList, WIDGETS.W_FILENAME)
-        # Background
-        self.mapper.addMapping(self.backgroundInput, WIDGETS.W_BACKGROUND_INPUT)
-        self.mapper.addMapping(self.estimateBgd, WIDGETS.W_ESTIMATE)
-        self.mapper.addMapping(self.manualBgd, WIDGETS.W_MANUAL_INPUT)
-
-        # Qmin/Qmax
-        self.mapper.addMapping(self.minQInput, WIDGETS.W_QMIN)
-        self.mapper.addMapping(self.maxQInput, WIDGETS.W_QMAX)
-
-        # Slit Parameter items
-        self.mapper.addMapping(self.slitWidthInput, WIDGETS.W_SLIT_WIDTH)
-        self.mapper.addMapping(self.slitHeightInput, WIDGETS.W_SLIT_HEIGHT)
-
-        # Parameter Items
-        self.mapper.addMapping(self.regularizationConstantInput,
-                               WIDGETS.W_REGULARIZATION)
-        self.mapper.addMapping(self.regConstantSuggestionButton,
-                               WIDGETS.W_REGULARIZATION_SUGGEST)
-        self.mapper.addMapping(self.explorerButton, WIDGETS.W_EXPLORE)
-        self.mapper.addMapping(self.maxDistanceInput, WIDGETS.W_MAX_DIST)
-        self.mapper.addMapping(self.noOfTermsInput, WIDGETS.W_NO_TERMS)
-        self.mapper.addMapping(self.noOfTermsSuggestionButton,
-                               WIDGETS.W_NO_TERMS_SUGGEST)
-
-        # Output
-        self.mapper.addMapping(self.rgValue, WIDGETS.W_RG)
-        self.mapper.addMapping(self.iQ0Value, WIDGETS.W_I_ZERO)
-        self.mapper.addMapping(self.backgroundValue, WIDGETS.W_BACKGROUND_OUTPUT)
-        self.mapper.addMapping(self.computationTimeValue, WIDGETS.W_COMP_TIME)
-        self.mapper.addMapping(self.chiDofValue, WIDGETS.W_CHI_SQUARED)
-        self.mapper.addMapping(self.oscillationValue, WIDGETS.W_OSCILLATION)
-        self.mapper.addMapping(self.posFractionValue, WIDGETS.W_POS_FRACTION)
-        self.mapper.addMapping(self.sigmaPosFractionValue,
-                               WIDGETS.W_SIGMA_POS_FRACTION)
-
-        # Main Buttons
-        self.mapper.addMapping(self.calculateButton, WIDGETS.W_CALCULATE)
-        self.mapper.addMapping(self.helpButton, WIDGETS.W_HELP)
-
-        self.mapper.toFirst()
-
-    def setupModel(self):
-        """
-        Update boxes with initial values
-        """
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_FILENAME, item)
-        item = QtGui.QStandardItem('0.0')
-        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_QMIN, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_QMAX, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_SLIT_WIDTH, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_SLIT_HEIGHT, item)
-        item = QtGui.QStandardItem("10")
-        self.model.setItem(WIDGETS.W_NO_TERMS, item)
-        item = QtGui.QStandardItem("0.0001")
-        self.model.setItem(WIDGETS.W_REGULARIZATION, item)
-        item = QtGui.QStandardItem("140.0")
-        self.model.setItem(WIDGETS.W_MAX_DIST, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_RG, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_I_ZERO, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_COMP_TIME, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_CHI_SQUARED, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_OSCILLATION, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_POS_FRACTION, item)
-        item = QtGui.QStandardItem("")
-        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION, item)
-
-    ######################################################################
-    # Methods for updating GUI
-
-    def enableButtons(self):
-        """
-        Enable buttons when data is present, else disable them
-        """
-        if self._has_data:
-            self.explorerButton.setEnabled(True)
-            self.calculateButton.setEnabled(True)
-        else:
-            self.calculateButton.setEnabled(False)
-            self.explorerButton.setEnabled(False)
-
-    def populateDataComboBox(self, filename):
-        """
-        Append a new file name to the data combobox
-        :param data: Data1D object
-        """
-        qt_item = QtCore.QString.fromUtf8(filename)
-        self.dataList.addItem(qt_item)
-
-    def acceptNoTerms(self):
-        """Send estimated no of terms to input"""
-        self.model.setItem(WIDGETS.W_NO_TERMS, QtGui.QStandardItem(
-            self.noOfTermsSuggestionButton.text()))
-
-    def acceptAlpha(self):
-        """Send estimated alpha to input"""
-        self.model.setItem(WIDGETS.W_REGULARIZATION, QtGui.QStandardItem(
-            self.regConstantSuggestionButton.text()))
-
-    ######################################################################
-    # GUI Interaction Events
-
-    def update_calculator(self):
-        """Update all p(r) params. Take all GUI values as an override"""
-        self._calculator.set_x(self._data.x)
-        self._calculator.set_y(self._data.y)
-        self._calculator.set_err(self._data.dy)
-        self._calculator.set_qmin(is_float(UI.TabbedPrInversionUI._fromUtf8(
-            self.minQInput.text())))
-        self._calculator.set_qmax(is_float(UI.TabbedPrInversionUI._fromUtf8(
-            self.maxQInput.text())))
-        self._calculator.set_alpha(is_float(UI.TabbedPrInversionUI._fromUtf8(
-            self.regularizationConstantInput.text())))
-        self._calculator.set_dmax(is_float(UI.TabbedPrInversionUI._fromUtf8(
-            self.maxDistanceInput.text())))
-        self._calculator.set_est_bck(int(is_float(
-            UI.TabbedPrInversionUI._fromUtf8(self.backgroundInput.text()))))
-        self._calculator.set_slit_height(is_float(
-            UI.TabbedPrInversionUI._fromUtf8(self.slitHeightInput.text())))
-        self._calculator.set_slit_width(is_float(
-            UI.TabbedPrInversionUI._fromUtf8(self.slitWidthInput.text())))
-
-    def _calculation(self):
-        """
-        Calculate the P(r) for every data set in the data list
-        """
-        # Pull in any GUI changes before running the calculations
-        self.update_calculator()
-        # Run
-        self.startThread()
-
-    def model_changed(self):
-        """Update the values when user makes changes"""
-        if not self.mapper:
-            return
-        self.mapper.toFirst()
-        # TODO: Update plots, etc.
-
-    def help(self):
-        """
-        Open the P(r) Inversion help browser
-        """
-        tree_location = (GuiUtils.HELP_DIRECTORY_LOCATION +
-                         "user/sasgui/perspectives/pr/pr_help.html")
-
-        # Actual file anchor will depend on the combo box index
-        # Note that we can be clusmy here, since bad current_fitter_id
-        # will just make the page displayed from the top
-        self._helpView.load(QtCore.QUrl(tree_location))
-        self._helpView.show()
-
-    def checkBgdClicked(self, boolean=None):
-        if boolean or self.manualBgd.isChecked():
-            self.manualBgd.setChecked(True)
-            self.toggleBgd(self.manualBgd)
-        else:
-            self.estimateBgd.setChecked(True)
-            self.toggleBgd(self.estimateBgd)
-
-    def toggleBgd(self, item=None):
-        """
-        Toggle the background between manual and estimated
-        :param item: gui item that was triggered
-        """
-        if not item:
-            self.checkBgdClicked()
-        elif isinstance(item, QtGui.QRadioButton):
-            if item is self.estimateBgd:
-                self.backgroundInput.setEnabled(False)
-            else:
-                self.backgroundInput.setEnabled(True)
-
-    def openExplorerWindow(self):
-        """
-        Open the Explorer window to see correlations between params and results
-        """
-        # TODO: This depends on SVCC-45
-        pass
-
-    ######################################################################
-    # Response Actions
-
-    def setData(self, data_item=None, is_batch=False):
-        """
-        Assign new data set or sets to the P(r) perspective
-        Obtain a QStandardItem object and dissect it to get Data1D/2D
-        Pass it over to the calculator
-        """
-        assert data_item is not None
-
-        if not isinstance(data_item, list):
-            msg = "Incorrect type passed to the P(r) Perspective"
-            raise AttributeError, msg
-
-        if not isinstance(data_item[0], QtGui.QStandardItem):
-            msg = "Incorrect type passed to the P(r) Perspective"
-            raise AttributeError, msg
-
-        for data in data_item:
-            data_object = GuiUtils.dataFromItem(data)
-            self._data_list.append({data_object: None})
-            self._has_data = True
-            self._data = data_object
-            self.enableButtons()
-            self.populateDataComboBox(data_object.filename)
-            self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem(
-                "{:.4g}".format(data_object.x.min())))
-            self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem(
-                "{:.4g}".format(data_object.x.max())))
-
-            # Estimate initial values from data
-            self.update_calculator()
-            self.performEstimate()
-
-            # TODO: Plot data on load
-
-            # TODO: Only load the 1st data until batch mode is working
-            # TODO: thus, the break
-            break
-
-    ######################################################################
-    # Thread Creators
-
-    def startThread(self):
-        """
-            Start a calculation thread
-        """
-        from PrThread import CalcPr
-
-        # If a thread is already started, stop it
-        if self.calc_thread is not None and self.calc_thread.isrunning():
-            self.calc_thread.stop()
-        pr = self._calculator.clone()
-        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
-            self.noOfTermsInput.text()))
-        self.calc_thread = CalcPr(pr, nfunc,
-                                  error_func=self._threadError,
-                                  completefn=self._completed, updatefn=None)
-        self.calc_thread.queue()
-        self.calc_thread.ready(2.5)
-
-    def performEstimateNT(self):
-        """
-            Perform parameter estimation
-        """
-        from PrThread import EstimateNT
-
-        # If a thread is already started, stop it
-        if (self.estimation_thread is not None and
-                self.estimation_thread.isrunning()):
-            self.estimation_thread.stop()
-        pr = self._calculator.clone()
-        # Skip the slit settings for the estimation
-        # It slows down the application and it doesn't change the estimates
-        pr.slit_height = 0.0
-        pr.slit_width = 0.0
-        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
-            self.noOfTermsInput.text()))
-        self.estimation_thread = EstimateNT(pr, nfunc,
-                                            error_func=self._threadError,
-                                            completefn=self._estimateNTCompleted,
-                                            updatefn=None)
-        self.estimation_thread.queue()
-        self.estimation_thread.ready(2.5)
-
-    def performEstimate(self):
-        """
-            Perform parameter estimation
-        """
-        from PrThread import EstimatePr
-
-        # If a thread is already started, stop it
-        if (self.estimation_thread is not None and
-                self.estimation_thread.isrunning()):
-            self.estimation_thread.stop()
-        pr = self._calculator.clone()
-        nfunc = int(UI.TabbedPrInversionUI._fromUtf8(
-            self.noOfTermsInput.text()))
-        self.estimation_thread = EstimatePr(pr, nfunc,
-                                            error_func=self._threadError,
-                                            completefn=self._estimateCompleted,
-                                            updatefn=None)
-        self.estimation_thread.queue()
-        self.estimation_thread.ready(2.5)
-
-    ######################################################################
-    # Thread Complete
-
-    def _estimateCompleted(self, alpha, message, elapsed):
-        """
-        Parameter estimation completed,
-        display the results to the user
-
-        :param alpha: estimated best alpha
-        :param elapsed: computation time
-        """
-        # Save useful info
-        self.model.setItem(WIDGETS.W_COMP_TIME,
-                           QtGui.QStandardItem(str(elapsed)))
-        self.regConstantSuggestionButton.setText(QtCore.QString(str(alpha)))
-        self.regConstantSuggestionButton.setEnabled(True)
-        if message:
-            logging.info(message)
-        self.performEstimateNT()
-
-    def _estimateNTCompleted(self, nterms, alpha, message, elapsed):
-        """
-        Parameter estimation completed,
-        display the results to the user
-
-        :param alpha: estimated best alpha
-        :param nterms: estimated number of terms
-        :param elapsed: computation time
-
-        """
-        # Save useful info
-        self.noOfTermsSuggestionButton.setText(QtCore.QString(
-            "{:n}".format(nterms)))
-        self.noOfTermsSuggestionButton.setEnabled(True)
-        self.regConstantSuggestionButton.setText(QtCore.QString(
-            "{:.3g}".format(alpha)))
-        self.regConstantSuggestionButton.setEnabled(True)
-        self.model.setItem(WIDGETS.W_COMP_TIME,
-                           QtGui.QStandardItem(str(elapsed)))
-        if message:
-            logging.info(message)
-            pass
-
-    def _completed(self, out, cov, pr, elapsed):
-        """
-        Method called with the results when the inversion is done
-
-        :param out: output coefficient for the base functions
-        :param cov: covariance matrix
-        :param pr: Invertor instance
-        :param elapsed: time spent computing
-
-        """
-        # Save useful info
-        # Keep a copy of the last result
-        self._last_calculator = pr.clone()
-
-        # TODO: Append to data dictionary
-        # self._data_list.append({s})
-
-        # Save Pr invertor
-        self._calculator = pr
-        cov = np.ascontiguousarray(cov)
-
-        # Show result on control panel
-
-        # TODO: Connect self._calculator to GUI
-        self.model.setItem(WIDGETS.W_RG, QtGui.QStandardItem(str(pr.rg(out))))
-        self.model.setItem(WIDGETS.W_I_ZERO,
-                           QtGui.QStandardItem(str(pr.iq0(out))))
-        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT,
-                           QtGui.QStandardItem("{:.3f}".format(pr.background)))
-        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT,
-                           QtGui.QStandardItem(str(pr.background)))
-        self.model.setItem(WIDGETS.W_CHI_SQUARED,
-                           QtGui.QStandardItem(str(pr.chi2[0])))
-        self.model.setItem(WIDGETS.W_COMP_TIME,
-                           QtGui.QStandardItem(str(elapsed)))
-        self.model.setItem(WIDGETS.W_OSCILLATION,
-                           QtGui.QStandardItem(str(pr.oscillations(out))))
-        self.model.setItem(WIDGETS.W_POS_FRACTION,
-                           QtGui.QStandardItem(str(pr.get_positive(out))))
-        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION,
-                           QtGui.QStandardItem(str(pr.get_pos_err(out, cov))))
-
-        # Display results tab
-        self.PrTabWidget.setCurrentIndex(1)
-
-        # TODO: Show plots
-        # Show I(q) fit
-        # self.show_iq(out, self._calculator)
-        # Show P(r) fit
-        # self.show_pr(out, self._calculator, cov)
-
-    def _threadError(self, error):
-        """
-            Call-back method for calculation errors
-        """
-        logging.warning(error)
-
-    def show_data(self, path=None, data=None, reset=False):
-        """
-        Show data read from a file
-
-        :param path: file path
-        :param reset: if True all other plottables will be cleared
-
-        """
-        if data is not None:
-            try:
-                pr = self._create_file_pr(data)
-            except:
-                status = "Problem reading data: %s" % sys.exc_value
-                raise RuntimeError, status
-
-            # If the file contains nothing, just return
-            if pr is None:
-                raise RuntimeError, "Loaded data is invalid"
-
-            self._calculator = pr
-
-        # Make a plot of I(q) data
-        if self._calculator.err is None:
-            logging.log(self._calculator.err)
-        else:
-            # TODO: Do something
-            pass
-        # Get Q range
-        #self.control_panel.q_min = min(self._calculator.x)
-        #self.control_panel.q_max = max(self._calculator.x)
Index: src/sas/qtgui/Perspectives/PrInversion/PrInversionUtils.py
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/PrInversionUtils.py	(revision dab3351971756716957029d75b8419fd076c18b0)
+++ 	(revision )
@@ -1,31 +1,0 @@
-def enum(*sequential, **named):
-    enums = dict(zip(sequential, range(len(sequential))), **named)
-    return type('Enum', (), enums)
-
-WIDGETS = enum( 'W_FILENAME',               #0
-                'W_BACKGROUND_INPUT',             #1
-                'W_ESTIMATE',               #2
-                'W_MANUAL_INPUT',           #3
-                'W_QMIN',                   #4
-                'W_QMAX',                   #5
-                'W_SLIT_HEIGHT',            #6
-                'W_SLIT_WIDTH',             #7
-                'W_NO_TERMS',               #8
-                'W_NO_TERMS_SUGGEST',       #9
-                'W_REGULARIZATION',         #10
-                'W_REGULARIZATION_SUGGEST', #11
-                'W_MAX_DIST',               #12
-                'W_EXPLORE',                #13
-                # results
-                'W_RG',
-                'W_I_ZERO',
-                'W_BACKGROUND_OUTPUT',
-                'W_COMP_TIME',
-                'W_CHI_SQUARED',
-                'W_OSCILLATION',
-                'W_POS_FRACTION',
-                'W_SIGMA_POS_FRACTION',
-                # bottom buttons
-                'W_CALCULATE',
-                'W_HELP'
-)
Index: src/sas/qtgui/Perspectives/PrInversion/PrThread.py
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/PrThread.py	(revision dab3351971756716957029d75b8419fd076c18b0)
+++ 	(revision )
@@ -1,104 +1,0 @@
-import sys
-import time
-from sas.sascalc.data_util.calcthread import CalcThread
-
-
-class CalcPr(CalcThread):
-    """
-    Compute P(r)
-    """
-
-    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
-                 updatefn=None, yieldtime=0.01, worktime=0.01):
-        """
-        """
-        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
-        self.pr = pr
-        self.nfunc = nfunc
-        self.error_func = error_func
-        self.starttime = 0
-
-    def compute(self):
-        """
-        Perform P(r) inversion
-        """
-        try:
-            self.starttime = time.time()
-            out, cov = self.pr.invert(self.nfunc)
-            elapsed = time.time() - self.starttime
-            self.complete(out=out, cov=cov, pr=self.pr, elapsed=elapsed)
-        except KeyboardInterrupt:
-            # Thread was interrupted, just proceed
-            pass
-        except:
-            if self.error_func is not None:
-                self.error_func("CalcPr.compute: %s" % sys.exc_value)
-
-
-class EstimatePr(CalcThread):
-    """
-    Estimate P(r)
-    """
-
-    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
-                 updatefn=None, yieldtime=0.01, worktime=0.01):
-        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
-        self.pr = pr
-        self.nfunc = nfunc
-        self.error_func = error_func
-        self.starttime = 0
-
-    def compute(self):
-        """
-        Calculates the estimate
-        """
-        try:
-            alpha, message, elapsed = self.pr.estimate_alpha(self.nfunc)
-            self.isquit()
-            self.complete(alpha=alpha, message=message, elapsed=elapsed)
-        except KeyboardInterrupt:
-            # Thread was interrupted, just proceed
-            pass
-        except:
-            if self.error_func is not None:
-                self.error_func("EstimatePr.compute: %s" % sys.exc_value)
-
-
-class EstimateNT(CalcThread):
-    """
-    """
-    def __init__(self, pr, nfunc=5, error_func=None, completefn=None,
-                 updatefn=None, yieldtime=0.01, worktime=0.01):
-        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
-        self.pr = pr
-        self.nfunc = nfunc
-        self.error_func = error_func
-        self.starttime = 0
-        self._time_for_sleep = 0
-        self._sleep_delay = 1.0
-
-    def isquit(self):
-        """
-        """
-        CalcThread.isquit(self)
-        if time.time() > self._time_for_sleep + self._sleep_delay:
-            time.sleep(.2)
-            self._time_for_sleep = time.time()
-
-    def compute(self):
-        """
-        Calculates the estimate
-        """
-        try:
-            t_0 = time.time()
-            self._time_for_sleep = t_0
-            nterms, alpha, message = self.pr.estimate_numterms(self.isquit)
-            t_1 = time.time() - t_0
-            self.isquit()
-            self.complete(nterms=nterms, alpha=alpha, message=message, elapsed=t_1)
-        except KeyboardInterrupt:
-            # Thread was interrupted, just proceed
-            pass
-        except:
-            if self.error_func is not None:
-                self.error_func("EstimatePr2.compute: %s" % sys.exc_value)
Index: src/sas/qtgui/Perspectives/PrInversion/UI/TabbedPrInversionUI.ui
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/UI/TabbedPrInversionUI.ui	(revision dab3351971756716957029d75b8419fd076c18b0)
+++ 	(revision )
@@ -1,595 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>PrInversion</class>
- <widget class="QDialog" name="PrInversion">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>458</width>
-    <height>500</height>
-   </rect>
-  </property>
-  <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-    <horstretch>0</horstretch>
-    <verstretch>0</verstretch>
-   </sizepolicy>
-  </property>
-  <property name="minimumSize">
-   <size>
-    <width>458</width>
-    <height>500</height>
-   </size>
-  </property>
-  <property name="maximumSize">
-   <size>
-    <width>458</width>
-    <height>500</height>
-   </size>
-  </property>
-  <property name="windowTitle">
-   <string>P(r) Inversion</string>
-  </property>
-  <layout class="QGridLayout" name="gridLayout_7">
-   <item row="3" column="0">
-    <layout class="QHBoxLayout" name="horizontalLayout_8">
-     <property name="sizeConstraint">
-      <enum>QLayout::SetDefaultConstraint</enum>
-     </property>
-     <item>
-      <widget class="QPushButton" name="calculateButton">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="text">
-        <string>Calculate</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer name="horizontalSpacer">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeType">
-        <enum>QSizePolicy::Expanding</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>40</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QPushButton" name="helpButton">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="text">
-        <string>Help</string>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item row="2" column="0">
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>2</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
-   <item row="1" column="0">
-    <widget class="QTabWidget" name="PrTabWidget">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="minimumSize">
-      <size>
-       <width>0</width>
-       <height>0</height>
-      </size>
-     </property>
-     <property name="currentIndex">
-      <number>0</number>
-     </property>
-     <widget class="QWidget" name="tabMain">
-      <attribute name="title">
-       <string>P(r) Parameters</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_6" stretch="0,1,1,0">
-       <item>
-        <widget class="QGroupBox" name="dataSourceGroupBox">
-         <property name="title">
-          <string>I(q) data source</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout_2">
-          <item row="1" column="0">
-           <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="2,1,0,2,2">
-            <item>
-             <widget class="QLabel" name="label_5">
-              <property name="text">
-               <string>Background Level:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="backgroundInput">
-              <property name="enabled">
-               <bool>false</bool>
-              </property>
-              <property name="text">
-               <string>0.0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_10">
-              <property name="text">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
-&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QRadioButton" name="estimateBgd">
-              <property name="text">
-               <string>Estimate</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QRadioButton" name="manualBgd">
-              <property name="text">
-               <string>Manual Input</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item row="0" column="0">
-           <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,3">
-            <item>
-             <widget class="QLabel" name="label">
-              <property name="text">
-               <string>Data File Name:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QComboBox" name="dataList"/>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="qRangeGroupBox">
-         <property name="title">
-          <string>Total Q range</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout_3">
-          <item row="0" column="0">
-           <layout class="QHBoxLayout" name="horizontalLayout_4">
-            <item>
-             <widget class="QLabel" name="label_7">
-              <property name="text">
-               <string>Min:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="minQInput">
-              <property name="enabled">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_11">
-              <property name="text">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
-&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_8">
-              <property name="text">
-               <string>Max:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="maxQInput">
-              <property name="enabled">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_9">
-              <property name="text">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
-&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="slitParamsGroupBox">
-         <property name="title">
-          <string>Slit Parameters</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout">
-          <item row="0" column="0">
-           <layout class="QHBoxLayout" name="horizontalLayout">
-            <item>
-             <widget class="QLabel" name="label_3">
-              <property name="text">
-               <string>Height</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="slitHeightInput">
-              <property name="enabled">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_6">
-              <property name="text">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
-&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_4">
-              <property name="text">
-               <string>Width</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="slitWidthInput">
-              <property name="enabled">
-               <bool>true</bool>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="label_2">
-              <property name="text">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ã
-&lt;span style=&quot; vertical-align:super;&quot;&gt;-1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="paramGroupBox">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="toolTip">
-          <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&gt;&lt;span style=&quot; font-family:'Courier New'; font-size:9pt; color:#000000;&quot;&gt;P(r) is found by fitting a set of base functions to I(Q). The minimization involves a regularization term to ensure a smooth P(r). The regularization constant gives the size of that term. The suggested value is the value above which the output P(r) will have only one peak.&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
-         </property>
-         <property name="title">
-          <string>Parameters</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout_8">
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_13">
-            <property name="text">
-             <string>Regularization constant</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="2">
-           <widget class="QPushButton" name="noOfTermsSuggestionButton">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="2">
-           <widget class="QPushButton" name="explorerButton">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open the D&lt;span style=&quot; vertical-align:sub;&quot;&gt;max&lt;/span&gt; explorer window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="layoutDirection">
-             <enum>Qt::LeftToRight</enum>
-            </property>
-            <property name="text">
-             <string>Explore</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="QLineEdit" name="noOfTermsInput"/>
-          </item>
-          <item row="2" column="1">
-           <widget class="QLineEdit" name="maxDistanceInput"/>
-          </item>
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_12">
-            <property name="text">
-             <string>Number of Terms</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="2">
-           <widget class="QPushButton" name="regConstantSuggestionButton">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="label_14">
-            <property name="text">
-             <string>Max distance [Ã
-]</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="QLineEdit" name="regularizationConstantInput"/>
-          </item>
-         </layout>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tabOptions">
-      <attribute name="title">
-       <string>Outputs</string>
-      </attribute>
-      <layout class="QGridLayout" name="gridLayout_6">
-       <item row="0" column="0">
-        <widget class="QGroupBox" name="outputsGroupBox">
-         <property name="title">
-          <string>Outputs</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout_4">
-          <item row="0" column="1">
-           <widget class="QLabel" name="label_23">
-            <property name="text">
-             <string>Calculated Value</string>
-            </property>
-            <property name="alignment">
-             <set>Qt::AlignCenter</set>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="2">
-           <widget class="QLabel" name="label_28">
-            <property name="text">
-             <string>Units</string>
-            </property>
-           </widget>
-          </item>
-          <item row="6" column="1">
-           <widget class="QLineEdit" name="oscillationValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="0">
-           <widget class="QLabel" name="label_17">
-            <property name="text">
-             <string>Background</string>
-            </property>
-           </widget>
-          </item>
-          <item row="7" column="1">
-           <widget class="QLineEdit" name="posFractionValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="2">
-           <widget class="QLabel" name="label_25">
-            <property name="text">
-             <string>Ã
--1</string>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="1">
-           <widget class="QLineEdit" name="backgroundValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_15">
-            <property name="text">
-             <string>Rg</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="2">
-           <widget class="QLabel" name="label_24">
-            <property name="text">
-             <string>Ã
-</string>
-            </property>
-           </widget>
-          </item>
-          <item row="6" column="0">
-           <widget class="QLabel" name="label_20">
-            <property name="text">
-             <string>Oscillations</string>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="0">
-           <widget class="QLabel" name="label_18">
-            <property name="text">
-             <string>Computation Time</string>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="2">
-           <widget class="QLabel" name="label_27">
-            <property name="text">
-             <string>secs</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="label_16">
-            <property name="text">
-             <string>I(Q=0)</string>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="2">
-           <widget class="QLabel" name="label_26">
-            <property name="text">
-             <string>Ã
--1</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_22">
-            <property name="text">
-             <string>Parameter</string>
-            </property>
-           </widget>
-          </item>
-          <item row="8" column="0">
-           <widget class="QLabel" name="label_29">
-            <property name="text">
-             <string>1-sigma positive fraction</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <widget class="QLineEdit" name="iQ0Value">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="5" column="0">
-           <widget class="QLabel" name="label_19">
-            <property name="text">
-             <string>Chi^2/dof</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="QLineEdit" name="rgValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="5" column="1">
-           <widget class="QLineEdit" name="chiDofValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="1">
-           <widget class="QLineEdit" name="computationTimeValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="7" column="0">
-           <widget class="QLabel" name="label_21">
-            <property name="text">
-             <string>Positive Fraction</string>
-            </property>
-           </widget>
-          </item>
-          <item row="8" column="1">
-           <widget class="QLineEdit" name="sigmaPosFractionValue">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item row="1" column="0">
-        <spacer name="verticalSpacer_2">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>20</width>
-           <height>40</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </widget>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
Index: src/sas/qtgui/Perspectives/PrInversion/UI/convert_all.bat
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/UI/convert_all.bat	(revision 6cbf8a546ab6300ef57ec41531f017182b1da8d6)
+++ 	(revision )
@@ -1,7 +1,0 @@
-@echo off
-
-for %%f in (*.ui) do (
-  call pyuic4.bat %%f > %%~nf.py
-)
-
-
Index: src/sas/qtgui/Perspectives/PrInversion/UI/convert_all.sh
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/UI/convert_all.sh	(revision 6cbf8a546ab6300ef57ec41531f017182b1da8d6)
+++ 	(revision )
@@ -1,6 +1,0 @@
-# UI -> PY
-for filename in *.ui; do
-  pyuic4 $filename > "`basename "$filename" .ui`.py"
-done
-
-
Index: src/sas/qtgui/Perspectives/PrInversion/UI/convert_ui.sh
===================================================================
--- src/sas/qtgui/Perspectives/PrInversion/UI/convert_ui.sh	(revision 6cbf8a546ab6300ef57ec41531f017182b1da8d6)
+++ 	(revision )
@@ -1,1 +1,0 @@
-pyuic.bat -w $1.ui > $1.py
Index: src/sas/qtgui/Perspectives/__init__.py
===================================================================
--- src/sas/qtgui/Perspectives/__init__.py	(revision e32b120ba1336ca42c470a629176b3acb1ad62d0)
+++ src/sas/qtgui/Perspectives/__init__.py	(revision e7651ffca46f55b1709d858d9c911c162adc332a)
@@ -4,9 +4,9 @@
 from Fitting.FittingPerspective import FittingWindow
 from Invariant.InvariantPerspective import InvariantWindow
-from PrInversion.PrInversionPerspective import PrInversionWindow
+from Inversion.InversionPerspective import InversionWindow
 
 PERSPECTIVES = {
     FittingWindow.name: FittingWindow,
     InvariantWindow.name: InvariantWindow,
-    PrInversionWindow.name: PrInversionWindow
+    InversionWindow.name: InversionWindow
 }
