Index: src/sas/sascalc/calculator/instrument.py
===================================================================
--- src/sas/sascalc/calculator/instrument.py	(revision b8080e1affadb04559f0597dfddc5506d2044e9d)
+++ src/sas/sascalc/calculator/instrument.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -128,5 +128,9 @@
             self.size = 0
         else:
-            self.size = size
+            # TODO: Make sure detector size is number of pixels
+            # Could be detector dimensions in e.g., mm, but
+            # the resolution calculator assumes it is pixels.
+            # Being pixels, it has to be integers rather than float
+            self.size = [int(s) for s in size]
             validate(size[0])
 
Index: src/sas/sascalc/calculator/sas_gen.py
===================================================================
--- src/sas/sascalc/calculator/sas_gen.py	(revision b8080e1affadb04559f0597dfddc5506d2044e9d)
+++ src/sas/sascalc/calculator/sas_gen.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -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/corfunc/corfunc_calculator.py
===================================================================
--- src/sas/sascalc/corfunc/corfunc_calculator.py	(revision 6ae74669a8e1dc1caf8f5be7dbb947be975651d9)
+++ src/sas/sascalc/corfunc/corfunc_calculator.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -30,11 +30,11 @@
             self.start = start
             self.stop = stop
-            self._lastx = []
-            self._lasty = []
+            self._lastx = np.empty(0, dtype='d')
+            self._lasty = None
 
         def __call__(self, x):
             # If input is a single number, evaluate the function at that number
             # and return a single number
-            if type(x) == float or type(x) == int:
+            if isinstance(x, (float, int)):
                 return self._smoothed_function(np.array([x]))[0]
             # If input is a list, and is different to the last input, evaluate
@@ -42,7 +42,6 @@
             # the function was called, return the result that was calculated
             # last time instead of explicity evaluating the function again.
-            elif self._lastx == [] or x.tolist() != self._lastx.tolist():
-                self._lasty = self._smoothed_function(x)
-                self._lastx = x
+            if not np.array_equal(x, self._lastx):
+                self._lastx, self._lasty = x, self._smoothed_function(x)
             return self._lasty
 
@@ -88,5 +87,5 @@
         # Only process data of the class Data1D
         if not issubclass(data.__class__, Data1D):
-            raise ValueError("Correlation function cannot be computed with 2D Data.")
+            raise ValueError("Correlation function cannot be computed with 2D data.")
 
         # Prepare the data
Index: src/sas/sascalc/corfunc/transform_thread.py
===================================================================
--- src/sas/sascalc/corfunc/transform_thread.py	(revision a859f9916f07adbcfeb4bebd403b46e6f32d18a7)
+++ src/sas/sascalc/corfunc/transform_thread.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -45,5 +45,5 @@
             # gamma3(R) = 1/R int_{0}^{R} gamma1(x) dx
             # trapz uses the trapezium rule to calculate the integral
-            mask = xs <= 200.0 # Only calculate gamma3 up to x=200 (as this is all that's plotted)
+            mask = xs <= 1000.0 # Only calculate gamma3 up to x=1000 (as this is all that's plotted)
             # gamma3 = [trapz(gamma1[:n], xs[:n])/xs[n-1] for n in range(2, len(xs[mask]) + 1)]j
             # gamma3.insert(0, 1.0) # Gamma_3(0) is defined as 1
@@ -79,5 +79,5 @@
 
         transform1 = Data1D(xs, gamma1)
-        transform3 = Data1D(xs[xs <= 200], gamma3)
+        transform3 = Data1D(xs[xs <= 1000], gamma3)
         idf = Data1D(xs, idf)
 
Index: src/sas/sascalc/data_util/calcthread.py
===================================================================
--- src/sas/sascalc/data_util/calcthread.py	(revision 574adc767a9e86744546f8edd6a23dc4f81914ad)
+++ src/sas/sascalc/data_util/calcthread.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -6,27 +6,22 @@
 from __future__ import print_function
 
-import traceback
 import sys
 import logging
+import traceback
+from time import sleep
+
 try:
     import _thread as thread
 except ImportError: # CRUFT: python 2 support
     import thread
-
-if sys.platform.count("darwin") > 0:
-    import time
-    stime = time.time()
-
-    def clock():
-        return time.time() - stime
-
-    def sleep(t):
-        return time.sleep(t)
-else:
-    from time import clock
-    from time import sleep
+try:
+    from time import perf_counter as clock
+except ImportError: # CRUFT: python < 3.3
+    if sys.platform.count("darwin") > 0:
+        from time import time as clock
+    else:
+        from time import clock
 
 logger = logging.getLogger(__name__)
-
 
 class CalcThread:
@@ -248,5 +243,5 @@
                 self.exception_handler(*sys.exc_info())
                 return
-            except Exception:
+            except Exception as exc:
                 pass
         logger.error(traceback.format_exc())
Index: src/sas/sascalc/data_util/ordereddicttest.py
===================================================================
--- src/sas/sascalc/data_util/ordereddicttest.py	(revision b699768550de9d4b35b087234ec1d2a461922bab)
+++ src/sas/sascalc/data_util/ordereddicttest.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -147,8 +147,8 @@
                     ]):
             self.assert_(dup is not od)
-            self.assertEquals(dup, od)
-            self.assertEquals(list(dup.items()), list(od.items()))
-            self.assertEquals(len(dup), len(od))
-            self.assertEquals(type(dup), type(od))
+            self.assertEqual(dup, od)
+            self.assertEqual(list(dup.items()), list(od.items()))
+            self.assertEqual(len(dup), len(od))
+            self.assertEqual(type(dup), type(od))
 
     def test_repr(self):
Index: src/sas/sascalc/dataloader/loader.py
===================================================================
--- src/sas/sascalc/dataloader/loader.py	(revision 8db20a9185da66f31aa0cd9f7af813e422f599ae)
+++ src/sas/sascalc/dataloader/loader.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -169,7 +169,7 @@
                         if self._identify_plugin(module):
                             readers_found += 1
-                    except:
+                    except Exception as exc:
                         msg = "Loader: Error importing "
-                        msg += "%s\n  %s" % (item, sys.exc_value)
+                        msg += "%s\n  %s" % (item, exc)
                         logger.error(msg)
 
@@ -191,12 +191,12 @@
                                 if self._identify_plugin(module):
                                     readers_found += 1
-                            except:
+                            except Exception as exc:
                                 msg = "Loader: Error importing"
-                                msg += " %s\n  %s" % (mfile, sys.exc_value)
+                                msg += " %s\n  %s" % (mfile, exc)
                                 logger.error(msg)
 
-                    except:
+                    except Exception as exc:
                         msg = "Loader: Error importing "
-                        msg += " %s\n  %s" % (item, sys.exc_value)
+                        msg += " %s\n  %s" % (item, exc)
                         logger.error(msg)
 
@@ -242,7 +242,7 @@
                     self.writers[ext].append(loader.write)
 
-            except:
+            except Exception as exc:
                 msg = "Loader: Error accessing"
-                msg += " Reader in %s\n  %s" % (module.__name__, sys.exc_value)
+                msg += " Reader in %s\n  %s" % (module.__name__, exc)
                 logger.error(msg)
         return reader_found
@@ -275,7 +275,7 @@
                     self.wildcards.append(wcard)
 
-        except:
+        except Exception as exc:
             msg = "Loader: Error accessing Reader "
-            msg += "in %s\n  %s" % (loader.__name__, sys.exc_value)
+            msg += "in %s\n  %s" % (loader.__name__, exc)
             logger.error(msg)
         return reader_found
@@ -320,7 +320,7 @@
                         self.writers[ext].insert(0, loader.write)
 
-            except:
+            except Exception as exc:
                 msg = "Loader: Error accessing Reader"
-                msg += " in %s\n  %s" % (module.__name__, sys.exc_value)
+                msg += " in %s\n  %s" % (module.__name__, exc)
                 logger.error(msg)
         return reader_found
Index: src/sas/sascalc/dataloader/manipulations.py
===================================================================
--- src/sas/sascalc/dataloader/manipulations.py	(revision 574adc767a9e86744546f8edd6a23dc4f81914ad)
+++ src/sas/sascalc/dataloader/manipulations.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -928,22 +928,23 @@
 
         # Organize the results
-        for i in range(self.nbins):
-            y[i] = y[i] / y_counts[i]
-            y_err[i] = math.sqrt(y_err[i]) / y_counts[i]
-
-            # The type of averaging: phi,q2, or q
-            # Calculate x[i]should be at the center of the bin
+        with np.errstate(divide='ignore', invalid='ignore'):
+            y = y/y_counts
+            y_err = np.sqrt(y_err)/y_counts
+            # The type of averaging: phi, q2, or q
+            # Calculate x values at the center of the bin
             if run.lower() == 'phi':
-                x[i] = (self.phi_max - self.phi_min) / self.nbins * \
-                    (1.0 * i + 0.5) + self.phi_min
+                step = (self.phi_max - self.phi_min) / self.nbins
+                x = (np.arange(self.nbins) + 0.5) * step + self.phi_min
             else:
-                # We take the center of ring area, not radius.
-                # This is more accurate than taking the radial center of ring.
-                # delta_r = (self.r_max - self.r_min) / self.nbins
-                # r_inner = self.r_min + delta_r * i
-                # r_outer = r_inner + delta_r
-                # x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2)
-                x[i] = x[i] / y_counts[i]
-        y_err[y_err == 0] = np.average(y_err)
+                # set q to the average of the q values within each bin
+                x = x/y_counts
+
+                ### Alternate algorithm
+                ## We take the center of ring area, not radius.
+                ## This is more accurate than taking the radial center of ring.
+                #step = (self.r_max - self.r_min) / self.nbins
+                #r_inner = self.r_min + step * np.arange(self.nbins)
+                #x = math.sqrt((r_inner**2 + (r_inner + step)**2) / 2)
+
         idx = (np.isfinite(y) & np.isfinite(y_err))
         if x_err is not None:
Index: src/sas/sascalc/dataloader/readers/associations.py
===================================================================
--- src/sas/sascalc/dataloader/readers/associations.py	(revision 8db20a9185da66f31aa0cd9f7af813e422f599ae)
+++ src/sas/sascalc/dataloader/readers/associations.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -54,6 +54,6 @@
                 exec("loader.associate_file_type('%s', %s)"
                      % (ext.upper(), reader))
-            except:
+            except Exception as exc:
                 msg = "read_associations: skipping association"
-                msg += " for %s\n  %s" % (ext.lower(), sys.exc_value)
+                msg += " for %s\n  %s" % (ext.lower(), exc)
                 logger.error(msg)
Index: src/sas/sascalc/fit/expression.py
===================================================================
--- src/sas/sascalc/fit/expression.py	(revision e4c475b769d2f7b453153dd47ec2824b13fe251d)
+++ src/sas/sascalc/fit/expression.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -188,12 +188,12 @@
 
     # Initialize dictionary with available functions
-    globals = {}
-    globals.update(math.__dict__)
-    globals.update(dict(arcsin=math.asin,arccos=math.acos,
+    global_context = {}
+    global_context.update(math.__dict__)
+    global_context.update(dict(arcsin=math.asin,arccos=math.acos,
                         arctan=math.atan,arctan2=math.atan2))
-    globals.update(context)
-    globals.update(parameters)
-    globals['id'] = id
-    locals = {}
+    global_context.update(context)
+    global_context.update(parameters)
+    global_context['id'] = id
+    local_context = {}
 
     # Define the constraints function
@@ -210,16 +210,15 @@
 
     #print("Function: "+functiondef)
-    # Python 2.7
-    #exec (functiondef in globals,locals)
-    # Python 3.5
-    exec (functiondef, globals, locals)
-
-    retfn = locals['eval_expressions']
+    # CRUFT: python < 3.0;  doc builder isn't allowing the following exec
+    # https://stackoverflow.com/questions/4484872/why-doesnt-exec-work-in-a-function-with-a-subfunction/41368813#comment73790496_41368813
+    #exec(functiondef, global_context, local_context)
+    eval(compile(functiondef, '<string>', 'exec'), global_context, local_context)
+    retfn = local_context['eval_expressions']
 
     # Remove garbage added to globals by exec
-    globals.pop('__doc__',None)
-    globals.pop('__name__',None)
-    globals.pop('__file__',None)
-    globals.pop('__builtins__')
+    global_context.pop('__doc__', None)
+    global_context.pop('__name__', None)
+    global_context.pop('__file__', None)
+    global_context.pop('__builtins__')
     #print globals.keys()
 
@@ -236,6 +235,7 @@
 
     # Break pairs into left set and right set
-    left,right = [set(s) for s in zip(*pairs)] if pairs != [] else ([],[])
-    while pairs != []:
+    # Note: pairs is array or list, so use "len(pairs) > 0" to check for empty.
+    left,right = [set(s) for s in zip(*pairs)] if len(pairs) > 0 else ([],[])
+    while len(pairs) > 0:
         #print "within",pairs
         # Find which items only occur on the right
@@ -265,5 +265,6 @@
     satisfies the partial ordering given by the pairs in partial order.
     """
-    left,right = zip(*pairs) if pairs != [] else ([],[])
+    # Note: pairs is array or list, so use "len(pairs) > 0" to check for empty.
+    left,right = zip(*pairs) if len(pairs) > 0 else ([],[])
     items = set(left)
     n = order_dependencies(pairs)
Index: src/sas/sascalc/fit/pagestate.py
===================================================================
--- src/sas/sascalc/fit/pagestate.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
+++ src/sas/sascalc/fit/pagestate.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -640,5 +640,6 @@
                 if len(value.strip()) == 0:
                     continue
-                title = value + " [" + repo_time + "]"
+                title = (value + " [" + repo_time + "] [SasView v" +
+                         SASVIEW_VERSION + "]")
                 title_name = HEADER % title
             elif name == "data":
@@ -649,7 +650,7 @@
                     #Truncating string so print doesn't complain of being outside margins
                     if sys.platform != "win32":
-                        MAX_STRING_LENGHT = 50
-                        if len(file_value) > MAX_STRING_LENGHT:
-                            file_value = "File name:.."+file_value[-MAX_STRING_LENGHT+10:]
+                        MAX_STRING_LENGTH = 50
+                        if len(file_value) > MAX_STRING_LENGTH:
+                            file_value = "File name:.."+file_value[-MAX_STRING_LENGTH+10:]
                     file_name = CENTRE % file_value
                     if len(title) == 0:
@@ -904,5 +905,5 @@
                 doc_model = newdoc.createElement('model_list_item')
                 doc_model.setAttribute('checked', str(model[0].GetValue()))
-                keys = model[1].keys()
+                keys = list(model[1].keys())
                 doc_model.setAttribute('name', str(keys[0]))
                 values = model[1].get(keys[0])
@@ -963,5 +964,5 @@
         if node.get('version'):
             # Get the version for model conversion purposes
-            x = re.sub('[^\d.]', '', node.get('version'))
+            x = re.sub(r'[^\d.]', '', node.get('version'))
             self.version = tuple(int(e) for e in str.split(x, "."))
             # The tuple must be at least 3 items long
@@ -983,7 +984,7 @@
                 try:
                     self.timestamp = float(entry.get('epoch'))
-                except Exception:
+                except Exception as exc:
                     msg = "PageState.fromXML: Could not"
-                    msg += " read timestamp\n %s" % sys.exc_value
+                    msg += " read timestamp\n %s" % exc
                     logger.error(msg)
 
Index: src/sas/sascalc/pr/distance_explorer.py
===================================================================
--- src/sas/sascalc/pr/distance_explorer.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ src/sas/sascalc/pr/distance_explorer.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -99,8 +99,8 @@
                 results.pos_err.append(pos_err)
                 results.osc.append(osc)
-            except:
+            except Exception as exc:
                 # This inversion failed, skip this D_max value
                 msg = "ExploreDialog: inversion failed for "
-                msg += "D_max=%s\n %s" % (str(d), sys.exc_value)
+                msg += "D_max=%s\n %s" % (str(d), exc)
                 results.errors.append(msg)
 
Index: src/sas/sascalc/pr/num_term.py
===================================================================
--- src/sas/sascalc/pr/num_term.py	(revision 57a91fc4ea8a687183c978326f77f3efaa8933ac)
+++ src/sas/sascalc/pr/num_term.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -182,6 +182,6 @@
                 data_y = np.append(data_y, test_y)
                 data_err = np.append(data_err, err)
-            except:
-                logger.error(sys.exc_value)
+            except Exception as exc:
+                logger.error(exc)
 
     return data_x, data_y, data_err
Index: src/sas/sascalc/realspace/VolumeCanvas.py
===================================================================
--- src/sas/sascalc/realspace/VolumeCanvas.py	(revision 98e3f24eb417c960360e014aae48605345a05266)
+++ src/sas/sascalc/realspace/VolumeCanvas.py	(revision 44a698c40441062ff38e78041080e655b87a9eb7)
@@ -472,5 +472,5 @@
             Return a list of the shapes
         """
-        return self.shapes.keys()
+        return list(self.shapes.keys())
 
     def _addSingleShape(self, shapeDesc):
