Index: docs/sphinx-docs/source/user/RELEASE.rst
===================================================================
--- docs/sphinx-docs/source/user/RELEASE.rst	(revision 9849f8a8d6479a7f8f4037eb8e9192e79fa86cf6)
+++ docs/sphinx-docs/source/user/RELEASE.rst	(revision 67ed5438043ca99c016f8a5ca333aea21e13ddc4)
@@ -60,4 +60,6 @@
 * An error in the be_polyelectrolyte model was identified and rectified, but 
   the fix is yet to be validated.
+* (Added post-release) An error with the reporting of the scale parameter 
+  from the spinodal model was rectified.
 * A number of issues and inconsistencies with the creation of
   sum|multiply models have been rectified.
@@ -187,5 +189,4 @@
 * Fixes #1010: Win64 build script not creating working executable
 * Fixes #1011: sld_test failing on ubuntu
-* Fixes #1012: ESS GUI not updating after fitting
 * Fixes #1013: FileReaderBaseClass output[] not reset - same file loaded multiple times
 * Fixes #1018: add Boltzmann distribution
@@ -233,4 +234,6 @@
 * Fixes #1179: PDF Report should contain SasView Version Number
 * Fixes #1183: Test from creating new model reset all parameters to default in all open FitPages
+* Fixes #1188: fitpage hangs if change model while magnetism is on
+* Fixes #1191: Correct erroneous Scale reported by Spinodal model
 
 **It is recommended that all users upgrade to this version, but your 
@@ -868,4 +871,6 @@
   found and corrected, corrected versions will be uploaded to the
   marketplace.
+* (Added after Release 4.2.0) The scale parameter reported from the spinodal 
+  model is the square root of the true value.
 
 3.1- All systems
Index: installers/license.txt
===================================================================
--- installers/license.txt	(revision 73c51df70c01e726ab1221981ae9cd24ab030bb3)
+++ installers/license.txt	(revision c6a4d1432c516fabc19624b0845742d0074dee0e)
@@ -8,9 +8,10 @@
 Participating facilities include (in alphabetical order): 
 the Australian National Science & Technology Centre for Neutron 
-Scattering, the Diamond Light Source, the European Spallation Source, 
-the Institut Laue Langevin, the ISIS Pulsed Neutron & Muon Source, 
-the National Institute of Standards & Technology Center for Neutron 
-Research, the Oak Ridge National Laboratory Neutron Sciences 
-Directorate, and the Technical University Delft Reactor Institute.
+Scattering, the Bundesanstalt fur Materialforschung und prufung, the 
+Diamond Light Source, the European Spallation Source, the Institut 
+Laue Langevin, the ISIS Pulsed Neutron & Muon Source, the National 
+Institute of Standards & Technology Center for Neutron Research, 
+the Oak Ridge National Laboratory Neutron Sciences Directorate, 
+and the Technical University Delft Reactor Institute.
 
 SasView is distributed under a 'Three-clause' BSD licence which you 
Index: run.py
===================================================================
--- run.py	(revision 33883379a0dbb7008f0c61b27d2f9a672c7542b0)
+++ run.py	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
@@ -95,15 +95,15 @@
     try:
         import periodictable
-    except:
+    except ImportError:
         addpath(joinpath(root, '..', 'periodictable'))
 
     try:
         import bumps
-    except:
+    except ImportError:
         addpath(joinpath(root, '..', 'bumps'))
 
     try:
         import tinycc
-    except:
+    except ImportError:
         addpath(joinpath(root, '../tinycc/build/lib'))
 
@@ -111,9 +111,28 @@
     #addpath(os.path.join(root, '..','wxPython-src-3.0.0.0','wxPython'))
 
+<<<<<<< HEAD
     # Build project if the build directory does not already exist.
     # PAK: with "update" we can always build since it is fast
     if rebuild or not os.path.exists(build_path):
+=======
+    # Put the sas source tree on the path
+    addpath(joinpath(root, 'src'))
+
+    # Put sasmodels on the path
+    addpath(joinpath(root, '../sasmodels/'))
+
+    # Check if the C extensions are already built
+    try:
+        from sas.sascalc.pr import _pr_inversion
+        from sas.sascalc.calculator import _sld2i
+        from sas.sascalc.file_converter import _bsl_loader
+    except ImportError:
+        rebuild = True
+
+    # Build C extensions if necessary.  Do an inplace build to simplify path.
+    if rebuild:
+>>>>>>> master
         import subprocess
-        build_cmd = [sys.executable, "setup.py", "build", "update"]
+        build_cmd = [sys.executable, "setup.py", "build_ext", "--inplace", "update"]
         if os.name == 'nt':
             build_cmd.append('--compiler=tinycc')
@@ -122,31 +141,4 @@
         with cd(root):
             subprocess.call(build_cmd, shell=shell)
-
-    # Put the source trees on the path
-    addpath(joinpath(root, 'src'))
-
-    # sasmodels on the path
-    addpath(joinpath(root, '../sasmodels/'))
-
-    # The sas.models package Compiled Model files should be pulled in from the build directory even though
-    # the source is stored in src/sas/models.
-
-    # Compiled modules need to be pulled from the build directory.
-    # Some packages are not where they are needed, so load them explicitly.
-    import sas.sascalc.pr
-    sas.sascalc.pr.core = import_package('sas.sascalc.pr.core',
-                                         joinpath(build_path, 'sas', 'sascalc', 'pr', 'core'))
-
-    # Compiled modules need to be pulled from the build directory.
-    # Some packages are not where they are needed, so load them explicitly.
-    import sas.sascalc.file_converter
-    sas.sascalc.file_converter.core = import_package('sas.sascalc.file_converter.core',
-                                                     joinpath(build_path, 'sas', 'sascalc', 'file_converter', 'core'))
-
-    import sas.sascalc.calculator
-    sas.sascalc.calculator.core = import_package('sas.sascalc.calculator.core',
-                                                 joinpath(build_path, 'sas', 'sascalc', 'calculator', 'core'))
-
-    sys.path.append(build_path)
 
     set_git_tag()
Index: setup.py
===================================================================
--- setup.py	(revision c16172d313e67da70e771029395ec7bd2bdba4e6)
+++ setup.py	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
@@ -12,9 +12,10 @@
 import shutil
 import sys
-from distutils.command.build_ext import build_ext
-from distutils.core import Command
 
 import numpy as np
+
 from setuptools import Extension, setup
+from setuptools import Command
+from setuptools.command.build_ext import build_ext
 
 try:
@@ -22,4 +23,7 @@
 except ImportError:
     pass
+
+# Convert "test" argument to "pytest" so 'python setup.py test' works
+sys.argv = [("pytest" if s == "test" else s) for s in sys.argv]
 
 # Manage version number ######################################
@@ -246,9 +250,8 @@
 # sas.sascalc.calculator
 gen_dir = os.path.join("src", "sas", "sascalc", "calculator", "c_extensions")
-package_dir["sas.sascalc.calculator.core"] = gen_dir
 package_dir["sas.sascalc.calculator"] = os.path.join(
     "src", "sas", "sascalc", "calculator")
-packages.extend(["sas.sascalc.calculator", "sas.sascalc.calculator.core"])
-ext_modules.append(Extension("sas.sascalc.calculator.core.sld2i",
+packages.append("sas.sascalc.calculator")
+ext_modules.append(Extension("sas.sascalc.calculator._sld2i",
                              sources=[
                                  os.path.join(gen_dir, "sld2i_module.c"),
@@ -258,13 +261,11 @@
                              ],
                              include_dirs=[gen_dir],
-                             )
-                   )
+                             ))
 
 # sas.sascalc.pr
 srcdir = os.path.join("src", "sas", "sascalc", "pr", "c_extensions")
-package_dir["sas.sascalc.pr.core"] = srcdir
 package_dir["sas.sascalc.pr"] = os.path.join("src", "sas", "sascalc", "pr")
-packages.extend(["sas.sascalc.pr", "sas.sascalc.pr.core"])
-ext_modules.append(Extension("sas.sascalc.pr.core.pr_inversion",
+packages.append("sas.sascalc.pr")
+ext_modules.append(Extension("sas.sascalc.pr._pr_inversion",
                              sources=[os.path.join(srcdir, "Cinvertor.c"),
                                       os.path.join(srcdir, "invertor.c"),
@@ -276,10 +277,8 @@
 # sas.sascalc.file_converter
 mydir = os.path.join("src", "sas", "sascalc", "file_converter", "c_ext")
-package_dir["sas.sascalc.file_converter.core"] = mydir
 package_dir["sas.sascalc.file_converter"] = os.path.join(
     "src", "sas", "sascalc", "file_converter")
-packages.extend(["sas.sascalc.file_converter",
-                 "sas.sascalc.file_converter.core"])
-ext_modules.append(Extension("sas.sascalc.file_converter.core.bsl_loader",
+packages.append("sas.sascalc.file_converter")
+ext_modules.append(Extension("sas.sascalc.file_converter._bsl_loader",
                              sources=[os.path.join(mydir, "bsl_loader.c")],
                              include_dirs=[np.get_include()],
@@ -443,4 +442,6 @@
     cmdclass={'build_ext': build_ext_subclass,
               'docs': BuildSphinxCommand,
-              'disable_openmp': DisableOpenMPCommand}
+              'disable_openmp': DisableOpenMPCommand},
+    setup_requires=['pytest-runner'] if 'pytest' in sys.argv else [],
+    tests_require=['pytest'],
 )
Index: c/sas/sascalc/calculator/c_extensions/__init__.py
===================================================================
--- src/sas/sascalc/calculator/c_extensions/__init__.py	(revision a57ae0704487b63fbba07d89eff101d45ec4a470)
+++ 	(revision )
@@ -1,3 +1,0 @@
-"""
-    C extensions to provide the sas_gen computations.
-"""
Index: src/sas/sascalc/calculator/c_extensions/sld2i_module.c
===================================================================
--- src/sas/sascalc/calculator/c_extensions/sld2i_module.c	(revision a1daf86c0d7d0aba84e29d778ffd6148e933d93a)
+++ src/sas/sascalc/calculator/c_extensions/sld2i_module.c	(revision 7ba64705ddaa18ab8bce14ae2ac2e767b23eb313)
@@ -2,6 +2,9 @@
   SLD2I module to perform point and I calculations
  */
+#include <stdio.h>
+
+//#define Py_LIMITED_API 0x03020000
 #include <Python.h>
-#include <stdio.h>
+
 #include "sld2i.h"
 
@@ -13,20 +16,24 @@
 #endif
 
-
-// Utilities
-#define INVECTOR(obj,buf,len)										\
-    do { \
-        int err = PyObject_AsReadBuffer(obj, (const void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
-#define OUTVECTOR(obj,buf,len) \
-    do { \
-        int err = PyObject_AsWriteBuffer(obj, (void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
+// Vector binding glue
+#if (PY_VERSION_HEX > 0x03000000) && !defined(Py_LIMITED_API)
+  // Assuming that a view into a writable vector points to a 
+  // non-changing pointer for the duration of the C call, capture 
+  // the view pointer and immediately free the view.
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    Py_buffer VEC_view; \
+    int VEC_err = PyObject_GetBuffer(VEC_obj, &VEC_view, PyBUF_WRITABLE|PyBUF_FORMAT); \
+    if (VEC_err < 0 || sizeof(*VEC_buf) != VEC_view.itemsize) return NULL; \
+    VEC_buf = (typeof(VEC_buf))VEC_view.buf; \
+    VEC_len = VEC_view.len/sizeof(*VEC_buf); \
+    PyBuffer_Release(&VEC_view); \
+  } while (0)
+#else
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    int VEC_err = PyObject_AsWriteBuffer(VEC_obj, (void **)(&VEC_buf), &VEC_len); \
+    if (VEC_err < 0) return NULL; \
+    VEC_len /= sizeof(*VEC_buf); \
+  } while (0)
+#endif
 
 /**
@@ -73,12 +80,12 @@
 	//printf("new GenI\n");
 	if (!PyArg_ParseTuple(args, "iOOOOOOOOddd", &is_avg, &x_val_obj, &y_val_obj, &z_val_obj, &sldn_val_obj, &mx_val_obj, &my_val_obj, &mz_val_obj, &vol_pix_obj, &inspin, &outspin, &stheta)) return NULL;
-	INVECTOR(x_val_obj, x_val, n_x);
-	INVECTOR(y_val_obj, y_val, n_y);
-	INVECTOR(z_val_obj, z_val, n_z);
-	INVECTOR(sldn_val_obj, sldn_val, n_sld);
-	INVECTOR(mx_val_obj, mx_val, n_mx);
-	INVECTOR(my_val_obj, my_val, n_my);
-	INVECTOR(mz_val_obj, mz_val, n_mz);
-	INVECTOR(vol_pix_obj, vol_pix, n_vol_pix);
+	VECTOR(x_val_obj, x_val, n_x);
+	VECTOR(y_val_obj, y_val, n_y);
+	VECTOR(z_val_obj, z_val, n_z);
+	VECTOR(sldn_val_obj, sldn_val, n_sld);
+	VECTOR(mx_val_obj, mx_val, n_mx);
+	VECTOR(my_val_obj, my_val, n_my);
+	VECTOR(mz_val_obj, mz_val, n_mz);
+	VECTOR(vol_pix_obj, vol_pix, n_vol_pix);
 	sld2i = PyMem_Malloc(sizeof(GenI));
 	//printf("sldi:%p\n", sld2i);
@@ -108,7 +115,7 @@
 	if (!PyArg_ParseTuple(args, "OOOO",  &gen_obj, &qx_obj, &qy_obj, &I_out_obj)) return NULL;
 	sld2i = (GenI *)PyCapsule_GetPointer(gen_obj, "GenI");
-	INVECTOR(qx_obj, qx, n_qx);
-	INVECTOR(qy_obj, qy, n_qy);
-	OUTVECTOR(I_out_obj, I_out, n_out);
+	VECTOR(qx_obj, qx, n_qx);
+	VECTOR(qy_obj, qy, n_qy);
+	VECTOR(I_out_obj, I_out, n_out);
 	//printf("qx, qy, I_out: %d %d %d, %d %d %d\n", qx, qy, I_out, n_qx, n_qy, n_out);
 
@@ -136,6 +143,6 @@
 	if (!PyArg_ParseTuple(args, "OOO",  &gen_obj, &q_obj, &I_out_obj)) return NULL;
 	sld2i = (GenI *)PyCapsule_GetPointer(gen_obj, "GenI");
-	INVECTOR(q_obj, q, n_q);
-	OUTVECTOR(I_out_obj, I_out, n_out);
+	VECTOR(q_obj, q, n_q);
+	VECTOR(I_out_obj, I_out, n_out);
 
 	// Sanity check
@@ -160,7 +167,7 @@
 
 #define MODULE_DOC "Sld2i C Library"
-#define MODULE_NAME "sld2i"
-#define MODULE_INIT2 initsld2i
-#define MODULE_INIT3 PyInit_sld2i
+#define MODULE_NAME "_sld2i"
+#define MODULE_INIT2 init_sld2i
+#define MODULE_INIT3 PyInit__sld2i
 #define MODULE_METHODS module_methods
 
Index: src/sas/sascalc/calculator/sas_gen.py
===================================================================
--- src/sas/sascalc/calculator/sas_gen.py	(revision 144e032af2559d8208e907563f404ab479862dbf)
+++ src/sas/sascalc/calculator/sas_gen.py	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
@@ -14,5 +14,5 @@
 import numpy as np
 
-from .core import sld2i as mod
+from . import _sld2i
 from .BaseComponent import BaseComponent
 
@@ -145,15 +145,15 @@
             self.params['Up_frac_out'],
             self.params['Up_theta'])
-        model = mod.new_GenI(*args)
+        model = _sld2i.new_GenI(*args)
         if len(qy):
             qx, qy = _vec(qx), _vec(qy)
             I_out = np.empty_like(qx)
             #print("npoints", qx.shape, "npixels", pos_x.shape)
-            mod.genicomXY(model, qx, qy, I_out)
+            _sld2i.genicomXY(model, qx, qy, I_out)
             #print("I_out after", I_out)
         else:
             qx = _vec(qx)
             I_out = np.empty_like(qx)
-            mod.genicom(model, qx, I_out)
+            _sld2i.genicom(model, qx, I_out)
         vol_correction = self.data_total_volume / self.params['total_volume']
         result = (self.params['scale'] * vol_correction * I_out
@@ -304,6 +304,6 @@
                 z_dir2 *= z_dir2
                 mask = (x_dir2 + y_dir2 + z_dir2) <= 1.0
-            except Exception:
-                logger.error(sys.exc_value)
+            except Exception as exc:
+                logger.error(exc)
         self.output = MagSLD(self.pos_x[mask], self.pos_y[mask],
                              self.pos_z[mask], self.sld_n[mask],
@@ -600,6 +600,6 @@
                         y_lines.append(y_line)
                         z_lines.append(z_line)
-                except Exception:
-                    logger.error(sys.exc_value)
+                except Exception as exc:
+                    logger.error(exc)
 
             output = MagSLD(pos_x, pos_y, pos_z, sld_n, sld_mx, sld_my, sld_mz)
@@ -691,9 +691,9 @@
                             _vol_pix = float(toks[7])
                             vol_pix = np.append(vol_pix, _vol_pix)
-                        except Exception:
+                        except Exception as exc:
                             vol_pix = None
-                    except Exception:
+                    except Exception as exc:
                         # Skip non-data lines
-                        logger.error(sys.exc_value)
+                        logger.error(exc)
             output = MagSLD(pos_x, pos_y, pos_z, sld_n,
                             sld_mx, sld_my, sld_mz)
Index: src/sas/sascalc/dataloader/file_reader_base_class.py
===================================================================
--- src/sas/sascalc/dataloader/file_reader_base_class.py	(revision 4a8d55c05d1355e27bf5afa880633879b6178acc)
+++ src/sas/sascalc/dataloader/file_reader_base_class.py	(revision fee520ecb8daf1211d988303a9ed0f650c777fb5)
@@ -276,5 +276,5 @@
                     dataset.xmax = np.max(dataset.qx_data)
                     dataset.ymin = np.min(dataset.qy_data)
-                    dataset.ymax = np.max(dataset.qx_data)
+                    dataset.ymax = np.max(dataset.qy_data)
 
     def format_unit(self, unit=None):
Index: src/sas/sascalc/file_converter/bsl_loader.py
===================================================================
--- src/sas/sascalc/file_converter/bsl_loader.py	(revision f00691d4eb5ea44608db5bc5dba2511a65165909)
+++ src/sas/sascalc/file_converter/bsl_loader.py	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
@@ -1,3 +1,3 @@
-from sas.sascalc.file_converter.core.bsl_loader import CLoader
+from sas.sascalc.file_converter._bsl_loader import CLoader
 from sas.sascalc.dataloader.data_info import Data2D
 from copy import deepcopy
@@ -67,5 +67,5 @@
                     'swap_bytes': int(metadata[3])
                 }
-            except:
+            except Exception:
                 is_valid = False
                 err_msg = "Invalid metadata in header file for {}"
Index: c/sas/sascalc/file_converter/c_ext/__init__.py
===================================================================
--- src/sas/sascalc/file_converter/c_ext/__init__.py	(revision a26f67f1457e7e39b79d4c3800c03bcaa208dff7)
+++ 	(revision )
@@ -1,3 +1,0 @@
-"""
-    Data loader for the Diamond BSL beamline.
-"""
Index: src/sas/sascalc/file_converter/c_ext/bsl_loader.c
===================================================================
--- src/sas/sascalc/file_converter/c_ext/bsl_loader.c	(revision d5aeaa3a97e3a88347ad8b3aad7acfd95e97de89)
+++ src/sas/sascalc/file_converter/c_ext/bsl_loader.c	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
@@ -1,8 +1,11 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+//#define Py_LIMITED_API 0x03020000
 #include <Python.h>
+#include <structmember.h>
 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 #include <numpy/arrayobject.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "structmember.h"
+
 #include "bsl_loader.h"
 
@@ -292,7 +295,7 @@
 
 #define MODULE_DOC "C module for loading bsl."
-#define MODULE_NAME "bsl_loader"
-#define MODULE_INIT2 initbsl_loader
-#define MODULE_INIT3 PyInit_bsl_loader
+#define MODULE_NAME "_bsl_loader"
+#define MODULE_INIT2 init_bsl_loader
+#define MODULE_INIT3 PyInit__bsl_loader
 #define MODULE_METHODS module_methods
 
Index: src/sas/sascalc/pr/c_extensions/Cinvertor.c
===================================================================
--- src/sas/sascalc/pr/c_extensions/Cinvertor.c	(revision a52f32f0dbf9ba217a21de95ba57c8862a042cad)
+++ src/sas/sascalc/pr/c_extensions/Cinvertor.c	(revision 7ba64705ddaa18ab8bce14ae2ac2e767b23eb313)
@@ -5,6 +5,4 @@
  *
  */
-#include <Python.h>
-#include "structmember.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -12,24 +10,33 @@
 #include <time.h>
 
+//#define Py_LIMITED_API 0x03050000
+#include <Python.h>
+#include <structmember.h>
+
+// Vector binding glue
+#if (PY_VERSION_HEX > 0x03000000) && !defined(Py_LIMITED_API)
+  // Assuming that a view into a writable vector points to a
+  // non-changing pointer for the duration of the C call, capture
+  // the view pointer and immediately free the view.
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    Py_buffer VEC_view; \
+    int VEC_err = PyObject_GetBuffer(VEC_obj, &VEC_view, PyBUF_WRITABLE|PyBUF_FORMAT); \
+    if (VEC_err < 0 || sizeof(*VEC_buf) != VEC_view.itemsize) return NULL; \
+    VEC_buf = (typeof(VEC_buf))VEC_view.buf; \
+    VEC_len = VEC_view.len/sizeof(*VEC_buf); \
+    PyBuffer_Release(&VEC_view); \
+  } while (0)
+#else
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    int VEC_err = PyObject_AsWriteBuffer(VEC_obj, (void **)(&VEC_buf), &VEC_len); \
+    if (VEC_err < 0) return NULL; \
+    VEC_len /= sizeof(*VEC_buf); \
+  } while (0)
+#endif
+
 #include "invertor.h"
-
 
 /// Error object for raised exceptions
 PyObject * CinvertorError;
-
-#define INVECTOR(obj,buf,len)										\
-    do { \
-        int err = PyObject_AsReadBuffer(obj, (const void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
-#define OUTVECTOR(obj,buf,len) \
-    do { \
-        int err = PyObject_AsWriteBuffer(obj, (void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
 
 // Class definition
@@ -99,5 +106,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.x);
@@ -131,5 +138,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -164,5 +171,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.y);
@@ -196,5 +203,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -229,5 +236,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.err);
@@ -261,5 +268,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -517,5 +524,5 @@
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
 
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
     // PyList of residuals
@@ -568,5 +575,5 @@
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
 
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	// Should create this list only once and refill it
@@ -609,5 +616,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &q)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	iq_value = iq(pars, self->params.d_max, (int)npars, q);
@@ -634,5 +641,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &q)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	iq_value = iq_smeared(pars, self->params.d_max, (int)npars,
@@ -659,5 +666,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &r)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	pr_value = pr(pars, self->params.d_max, (int)npars, r);
@@ -686,5 +693,5 @@
 
 	if (!PyArg_ParseTuple(args, "OOd", &data_obj, &err_obj, &r)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	if (err_obj == Py_None) {
@@ -692,5 +699,5 @@
 		pr_err_value = 0.0;
 	} else {
-		OUTVECTOR(err_obj,pars_err,npars2);
+		VECTOR(err_obj,pars_err,npars2);
 		pr_err(pars, pars_err, self->params.d_max, (int)npars, r, &pr_value, &pr_err_value);
 	}
@@ -726,5 +733,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	oscill = reg_term(pars, self->params.d_max, (int)npars, 100);
@@ -747,5 +754,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	count = npeaks(pars, self->params.d_max, (int)npars, 100);
@@ -768,5 +775,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	fraction = positive_integral(pars, self->params.d_max, (int)npars, 100);
@@ -792,6 +799,6 @@
 
 	if (!PyArg_ParseTuple(args, "OO", &data_obj, &err_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
-	OUTVECTOR(err_obj,pars_err,npars2);
+	VECTOR(data_obj,pars,npars);
+	VECTOR(err_obj,pars_err,npars2);
 
 	fraction = positive_errors(pars, pars_err, self->params.d_max, (int)npars, 51);
@@ -813,5 +820,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	value = rg(pars, self->params.d_max, (int)npars, 101);
@@ -833,5 +840,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	value = 4.0*acos(-1.0)*int_pr(pars, self->params.d_max, (int)npars, 101);
@@ -874,6 +881,6 @@
 
 	if (!PyArg_ParseTuple(args, "iiOO", &nfunc, &nr, &a_obj, &b_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
-	OUTVECTOR(b_obj,b,n_b);
+	VECTOR(a_obj,a,n_a);
+	VECTOR(b_obj,b,n_b);
 
 	assert(n_b>=nfunc);
@@ -947,6 +954,6 @@
 
 	if (!PyArg_ParseTuple(args, "iiOO", &nfunc, &nr, &a_obj, &cov_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
-	OUTVECTOR(cov_obj,inv_cov,n_cov);
+	VECTOR(a_obj,a,n_a);
+	VECTOR(cov_obj,inv_cov,n_cov);
 
 	assert(n_cov>=nfunc*nfunc);
@@ -981,5 +988,5 @@
 
 	if (!PyArg_ParseTuple(args, "iiO", &nfunc, &nr, &a_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
+	VECTOR(a_obj,a,n_a);
 
 	assert(n_a>=nfunc*(nr+self->params.npoints));
@@ -1121,7 +1128,7 @@
 
 #define MODULE_DOC "C extension module for inversion to P(r)."
-#define MODULE_NAME "pr_inversion"
-#define MODULE_INIT2 initpr_inversion
-#define MODULE_INIT3 PyInit_pr_inversion
+#define MODULE_NAME "_pr_inversion"
+#define MODULE_INIT2 init_pr_inversion
+#define MODULE_INIT3 PyInit__pr_inversion
 #define MODULE_METHODS module_methods
 
Index: c/sas/sascalc/pr/c_extensions/__init__.py
===================================================================
--- src/sas/sascalc/pr/c_extensions/__init__.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ 	(revision )
@@ -1,3 +1,0 @@
-"""
-    C extensions to provide the P(r) inversion computations.
-"""
Index: src/sas/sascalc/pr/fit/BumpsFitting.py
===================================================================
--- src/sas/sascalc/pr/fit/BumpsFitting.py	(revision 9a5097cd1c76689d1f997b85ba43d12a95d8f243)
+++ src/sas/sascalc/pr/fit/BumpsFitting.py	(revision 3e6829d03839dc7a60382a887dc7f27da1c50c8f)
@@ -2,4 +2,6 @@
 BumpsFitting module runs the bumps optimizer.
 """
+from __future__ import division
+
 import os
 from datetime import timedelta, datetime
@@ -34,5 +36,5 @@
 class Progress(object):
     def __init__(self, history, max_step, pars, dof):
-        remaining_time = int(history.time[0]*(float(max_step)/history.step[0]-1))
+        remaining_time = int(history.time[0]*(max_step/history.step[0]-1))
         # Depending on the time remaining, either display the expected
         # time of completion, or the amount of time remaining.  Use precision
Index: src/sas/sascalc/pr/fit/Loader.py
===================================================================
--- src/sas/sascalc/pr/fit/Loader.py	(revision 574adc767a9e86744546f8edd6a23dc4f81914ad)
+++ src/sas/sascalc/pr/fit/Loader.py	(revision 57e48ca3fba05a5ace7a3f2a5b6ff8f1a9f4206c)
@@ -1,7 +1,8 @@
+"""
+class Loader  to load any kind of file
+"""
+
 from __future__ import print_function
 
-# class Loader  to load any king of file
-#import wx
-#import string
 import numpy as np
 
Index: src/sas/sascalc/pr/invertor.py
===================================================================
--- src/sas/sascalc/pr/invertor.py	(revision 2469df7fc9ffa047115c5bffe589ed307b12c363)
+++ src/sas/sascalc/pr/invertor.py	(revision 57e48ca3fba05a5ace7a3f2a5b6ff8f1a9f4206c)
@@ -6,4 +6,5 @@
 FIXME: The way the Invertor interacts with its C component should be cleaned up
 """
+from __future__ import division
 
 import numpy as np
@@ -17,5 +18,5 @@
 from numpy.linalg import lstsq
 from scipy import optimize
-from sas.sascalc.pr.core.pr_inversion import Cinvertor
+from sas.sascalc.pr._pr_inversion import Cinvertor
 
 logger = logging.getLogger(__name__)
@@ -71,5 +72,5 @@
         A[j][i] = (Fourier transformed base function for point j)
 
-    We them choose a number of r-points, n_r, to evaluate the second
+    We then choose a number of r-points, n_r, to evaluate the second
     derivative of P(r) at. This is used as our regularization term.
     For a vector r of length n_r, the following n_r rows are set to ::
@@ -144,5 +145,5 @@
         x, y, err, d_max, q_min, q_max and alpha
         """
-        if   name == 'x':
+        if name == 'x':
             if 0.0 in value:
                 msg = "Invertor: one of your q-values is zero. "
@@ -268,5 +269,5 @@
             A[i][j] = (Fourier transformed base function for point j)
 
-        We them choose a number of r-points, n_r, to evaluate the second
+        We then choose a number of r-points, n_r, to evaluate the second
         derivative of P(r) at. This is used as our regularization term.
         For a vector r of length n_r, the following n_r rows are set to ::
@@ -416,5 +417,5 @@
             A[i][j] = (Fourier transformed base function for point j)
 
-        We them choose a number of r-points, n_r, to evaluate the second
+        We then choose a number of r-points, n_r, to evaluate the second
         derivative of P(r) at. This is used as our regularization term.
         For a vector r of length n_r, the following n_r rows are set to ::
@@ -473,5 +474,5 @@
 
         # Perform the inversion (least square fit)
-        c, chi2, _, _ = lstsq(a, b)
+        c, chi2, _, _ = lstsq(a, b, rcond=-1)
         # Sanity check
         try:
@@ -496,9 +497,9 @@
         try:
             cov = np.linalg.pinv(inv_cov)
-            err = math.fabs(chi2 / float(npts - nfunc)) * cov
-        except:
+            err = math.fabs(chi2 / (npts - nfunc)) * cov
+        except Exception as exc:
             # We were not able to estimate the errors
             # Return an empty error matrix
-            logger.error(sys.exc_value)
+            logger.error(exc)
 
         # Keep a copy of the last output
@@ -537,13 +538,13 @@
 
         """
-        from num_term import NTermEstimator
+        from .num_term import NTermEstimator
         estimator = NTermEstimator(self.clone())
         try:
             return estimator.num_terms(isquit_func)
-        except:
+        except Exception as exc:
             # If we fail, estimate alpha and return the default
             # number of terms
             best_alpha, _, _ = self.estimate_alpha(self.nfunc)
-            logger.warning("Invertor.estimate_numterms: %s" % sys.exc_value)
+            logger.warning("Invertor.estimate_numterms: %s" % exc)
             return self.nfunc, best_alpha, "Could not estimate number of terms"
 
@@ -631,6 +632,6 @@
                 return best_alpha, message, elapsed
 
-        except:
-            message = "Invertor.estimate_alpha: %s" % sys.exc_value
+        except Exception as exc:
+            message = "Invertor.estimate_alpha: %s" % exc
             return 0, message, elapsed
 
@@ -748,6 +749,6 @@
                         self.cov[i][i] = float(toks2[1])
 
-            except:
-                msg = "Invertor.from_file: corrupted file\n%s" % sys.exc_value
+            except Exception as exc:
+                msg = "Invertor.from_file: corrupted file\n%s" % exc
                 raise RuntimeError(msg)
         else:
Index: src/sas/sascalc/pr/num_term.py
===================================================================
--- src/sas/sascalc/pr/num_term.py	(revision 2469df7fc9ffa047115c5bffe589ed307b12c363)
+++ src/sas/sascalc/pr/num_term.py	(revision 3e6829d03839dc7a60382a887dc7f27da1c50c8f)
@@ -1,3 +1,3 @@
-from __future__ import print_function
+from __future__ import print_function, division
 
 import math
@@ -51,5 +51,5 @@
         osc = self.sort_osc()
         dv = len(osc)
-        med = float(dv) / 2.0
+        med = 0.5*dv
         odd = self.is_odd(dv)
         medi = 0
@@ -140,5 +140,5 @@
             nts = self.compare_err()
             div = len(nts)
-            tem = float(div) / 2.0
+            tem = 0.5*div
             if self.is_odd(div):
                 nt = nts[int(tem)]
Index: src/sas/sasgui/perspectives/fitting/basepage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/basepage.py	(revision b43988196e5c4f2dfbf3ec5c9b66703d5656b08d)
+++ src/sas/sasgui/perspectives/fitting/basepage.py	(revision 5323490d62009a786d3d071b2197b51ce207354d)
@@ -2884,9 +2884,9 @@
             self.magnetic_on = True
             button.SetLabel("Magnetic OFF")
-            m_value = 1.0e-06
+            m_value = 1
             for key in self.model.magnetic_params:
                 if key.count('M0') > 0:
                     self.model.setParam(key, m_value)
-                    m_value += 0.5e-06
+                    m_value += 0.5
         else:
             self.magnetic_on = False
Index: src/sas/sasgui/perspectives/fitting/gpu_options.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/gpu_options.py	(revision 388aefbfe7862efae1f1595105c7a8b53bb3e8e3)
+++ src/sas/sasgui/perspectives/fitting/gpu_options.py	(revision 8e109f9b4b47319e1f698a4c5e4e57a3a51656d3)
@@ -8,9 +8,21 @@
 '''
 
+import json
+import platform
 import logging
 import os
 import sys
+
 import wx
+
+try:
+    import pyopencl as cl
+except ImportError:
+    cl = None
+
 import sasmodels
+import sasmodels.model_test
+import sasmodels.kernelcl
+
 from sas.sasgui.guiframe.documentation_window import DocumentationWindow
 
@@ -169,16 +181,17 @@
         clinfo = []
         platforms = []
-        try:
-            import pyopencl as cl
-            platforms = cl.get_platforms()
-        except ImportError:
+
+        if cl is None:
             logger.warn("Unable to import the pyopencl package.  It may not "
                         "have been installed.  If you wish to use OpenCL, try "
                         "running pip install --user pyopencl")
-        except cl.LogicError as err:
-            logger.warn("Unable to fetch the OpenCL platforms.  This likely "
-                        "means that the opencl drivers for your system are "
-                        "not installed.")
-            logger.warn(err)
+        else:
+            try:
+                platforms = cl.get_platforms()
+            except cl.LogicError as err:
+                logger.warn("Unable to fetch the OpenCL platforms.  This likely "
+                            "means that the opencl drivers for your system are "
+                            "not installed.")
+                logger.warn(err)
 
         p_index = 0
@@ -226,10 +239,5 @@
             if "SAS_OPENCL" in os.environ:
                 del os.environ["SAS_OPENCL"]
-
-        #Sasmodels kernelcl doesn't exist when initiated with None
-        if 'sasmodels.kernelcl' in sys.modules:
-            sasmodels.kernelcl.ENV = None
-
-        reload(sasmodels.core)
+        sasmodels.kernelcl.reset_environment()
         event.Skip()
 
@@ -247,8 +255,4 @@
         Run sasmodels check from here and report results from
         """
-        import json
-        import platform
-        #import sasmodels
-
         #The same block of code as for OK but it is needed if we want to have
         #active response to Test button
@@ -261,19 +265,8 @@
             if "SAS_OPENCL" in os.environ:
                 del os.environ["SAS_OPENCL"]
-
-        #Sasmodels kernelcl doesn't exist when initiated with None
-        if 'sasmodels.kernelcl' in sys.modules:
-            sasmodels.kernelcl.ENV = None
-
-
-        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
-        reload(sasmodels.core)
-
-
-        from sasmodels.model_test import model_tests
+        sasmodels.kernelcl.reset_environment()
 
         try:
-            from sasmodels.kernelcl import environment
-            env = environment()
+            env = sasmodels.kernelcl.environment()
             clinfo = [(ctx.devices[0].platform.vendor,
                        ctx.devices[0].platform.version,
@@ -282,10 +275,10 @@
                        ctx.devices[0].version)
                       for ctx in env.context]
-        except ImportError:
+        except Exception:
             clinfo = None
 
         failures = []
         tests_completed = 0
-        for test in model_tests():
+        for test in sasmodels.model_test.model_tests():
             try:
                 test()
