Index: docs/sphinx-docs/source/conf.py
===================================================================
--- docs/sphinx-docs/source/conf.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ docs/sphinx-docs/source/conf.py	(revision 6394851e9ff662a22e84b744274580762e427d72)
@@ -39,4 +39,7 @@
               'sphinx.ext.viewcode']
 
+#set mathjax path
+mathjax_path="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"
+
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -62,5 +65,5 @@
 version = '4.1'
 # The full version, including alpha/beta/rc tags.
-release = '4.1.0'
+release = '4.1.2'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
Index: sasview/README.txt
===================================================================
--- sasview/README.txt	(revision 311d00ac4610077e51142b4b69182cd5b95f3211)
+++ sasview/README.txt	(revision 6394851e9ff662a22e84b744274580762e427d72)
@@ -4,4 +4,27 @@
 1- Features
 ===========
+    - New in Version 4.1.2
+      --------------------
+      This point release is a bug-fix release addressing:
+
+       - Fixes #984: PDF Reports Generate Empty PDFs
+       - Fixes a path typo
+       - 64 bit and 32 bit Windows executables now available
+
+      It is recommended that all users upgrade to this version
+
+    - New in Version 4.1.1
+      --------------------
+      This point release is a bug-fix release addressing:
+
+       - Fixes #948: Mathjax CDN is going away
+       - Fixes #938: Cannot read canSAS1D file output by SasView
+       - Fixes #960: Save project throws error if empty fit page
+       - Fixes #929: Problem deleting data in first fit page
+       - Fixes #918: Test folders not bundled with release
+       - Fixes an issue with the live discovery of plugin models
+       - Fixes an issue with the NXcanSAS data loader
+       - Updated tutorials for SasView 4.x.y
+
     - New in Version 4.1.0
       ------------------
Index: sasview/__init__.py
===================================================================
--- sasview/__init__.py	(revision 463e7ffce130ae386f93cd18b87a1120743e88b5)
+++ sasview/__init__.py	(revision 6394851e9ff662a22e84b744274580762e427d72)
@@ -1,3 +1,3 @@
-__version__ = "4.1"
+__version__ = "4.1.2"
 __build__ = "GIT_COMMIT"
 
Index: sasview/local_config.py
===================================================================
--- sasview/local_config.py	(revision a1b8fee73528559155793dd74cda07d0c32e9d72)
+++ sasview/local_config.py	(revision d9089328dec4c154a6bac2735e52b5e6fb3c8af2)
@@ -47,5 +47,5 @@
 '''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.'''
 _acknowledgement_citation = \
-'''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138'''
+'''M. Doucet et al. SasView Version 4.1.2, Zenodo, 10.5281/zenodo.825675'''
 
 _acknowledgement =  \
Index: sasview/sasview.spec
===================================================================
--- sasview/sasview.spec	(revision e42c8e9da0efedb482d84a029b0a02f1e865fa34)
+++ sasview/sasview.spec	(revision 945f45dffd0457ae7d515e67140f82a55c862e9e)
@@ -138,5 +138,6 @@
  'sasmodels.core',
  'pyopencl',
- 'tinycc'
+ 'tinycc',
+ 'xhtml2pdf'
 ]
 
Index: sasview/setup_exe.py
===================================================================
--- sasview/setup_exe.py	(revision a1b8fee73528559155793dd74cda07d0c32e9d72)
+++ sasview/setup_exe.py	(revision 3563e064d32ce6574afed77008d59372e6bb54ab)
@@ -179,6 +179,10 @@
 test_1d_dir = os.path.join(path, "test\\1d_data")
 test_2d_dir = os.path.join(path, "test\\2d_data")
+test_sesans_dir = os.path.join(path, "test\\sesans_data")
+test_convertible_dir = os.path.join(path, "test\\convertible_files")
 test_save_dir = os.path.join(path, "test\\save_states")
-test_upcoming_dir = os.path.join(path, "test\\upcoming_formats")
+test_coord_dir = os.path.join(path, "test\\coordinate_data")
+test_image_dir = os.path.join(path, "test\\image_data")
+test_other_dir = os.path.join(path, "test\\other_files")
 
 matplotlibdatadir = matplotlib.get_data_path()
@@ -269,31 +273,27 @@
 # Copying the images directory to the distribution directory.
 for f in findall(images_dir):
-    if not ".svn" in f:
-        data_files.append(("images", [f]))
+    data_files.append(("images", [f]))
 
 # Copying the HTML help docs
 for f in findall(media_dir):
-    if not ".svn" in f:
-        data_files.append(("media", [f]))
+    data_files.append(("media", [f]))
 
 # Copying the sample data user data
 for f in findall(test_1d_dir):
-    if not ".svn" in f:
-        data_files.append(("test\\1d_data", [f]))
-
-# Copying the sample data user data
+    data_files.append(("test\\1d_data", [f]))
 for f in findall(test_2d_dir):
-    if not ".svn" in f:
-        data_files.append(("test\\2d_data", [f]))
-
-# Copying the sample data user data
+    data_files.append(("test\\2d_data", [f]))
 for f in findall(test_save_dir):
-    if not ".svn" in f:
-        data_files.append(("test\\save_states", [f]))
-
-# Copying the sample data user data
-for f in findall(test_upcoming_dir):
-    if not ".svn" in f:
-        data_files.append(("test\\upcoming_formats", [f]))
+    data_files.append(("test\\save_states", [f]))
+for f in findall(test_sesans_dir):
+    data_files.append(("test\\sesans_data", [f]))
+for f in findall(test_convertible_dir):
+    data_files.append(("test\\convertible_files", [f]))
+for f in findall(test_coord_dir):
+    data_files.append(("test\\coordinate_data", [f]))
+for f in findall(test_image_dir):
+    data_files.append(("test\\image_data", [f]))
+for f in findall(test_other_dir):
+    data_files.append(("test\\other_files", [f]))
 
 # Copying opencl include files
Index: src/sas/sascalc/dataloader/file_reader_base_class.py
===================================================================
--- src/sas/sascalc/dataloader/file_reader_base_class.py	(revision a78a02fe90f1c962f523301685c143a27f11ba7d)
+++ src/sas/sascalc/dataloader/file_reader_base_class.py	(revision ae69c690bae8eb1cae0c6902dd71755dda9710f8)
@@ -115,4 +115,7 @@
                 data.y = np.asarray([data.y[i] for i in ind]).astype(np.float64)
                 if data.dx is not None:
+                    if len(data.dx) == 0:
+                        data.dx = None
+                        continue
                     data.dx = np.asarray([data.dx[i] for i in ind]).astype(np.float64)
                 if data.dxl is not None:
@@ -121,4 +124,7 @@
                     data.dxw = np.asarray([data.dxw[i] for i in ind]).astype(np.float64)
                 if data.dy is not None:
+                    if len(data.dy) == 0:
+                        data.dy = None
+                        continue
                     data.dy = np.asarray([data.dy[i] for i in ind]).astype(np.float64)
                 if data.lam is not None:
@@ -185,5 +191,6 @@
         self.output = []
 
-    def remove_empty_q_values(self, has_error_dx=False, has_error_dy=False):
+    def remove_empty_q_values(self, has_error_dx=False, has_error_dy=False,
+                              has_error_dxl=False, has_error_dxw=False):
         """
         Remove any point where Q == 0
@@ -192,8 +199,12 @@
         self.current_dataset.x = self.current_dataset.x[x != 0]
         self.current_dataset.y = self.current_dataset.y[x != 0]
-        self.current_dataset.dy = self.current_dataset.dy[x != 0] if \
-            has_error_dy else np.zeros(len(self.current_dataset.y))
-        self.current_dataset.dx = self.current_dataset.dx[x != 0] if \
-            has_error_dx else np.zeros(len(self.current_dataset.x))
+        if has_error_dy:
+            self.current_dataset.dy = self.current_dataset.dy[x != 0]
+        if has_error_dx:
+            self.current_dataset.dx = self.current_dataset.dx[x != 0]
+        if has_error_dxl:
+            self.current_dataset.dxl = self.current_dataset.dxl[x != 0]
+        if has_error_dxw:
+            self.current_dataset.dxw = self.current_dataset.dxw[x != 0]
 
     def reset_data_list(self, no_lines=0):
@@ -204,6 +215,6 @@
         x = np.zeros(no_lines)
         y = np.zeros(no_lines)
+        dx = np.zeros(no_lines)
         dy = np.zeros(no_lines)
-        dx = np.zeros(no_lines)
         self.current_dataset = plottable_1D(x, y, dx, dy)
 
Index: src/sas/sascalc/dataloader/readers/cansas_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision a78a02fe90f1c962f523301685c143a27f11ba7d)
+++ src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision ae69c690bae8eb1cae0c6902dd71755dda9710f8)
@@ -130,10 +130,5 @@
                 self.current_datainfo.meta_data[PREPROCESS] = self.processing_instructions
                 self._parse_entry(entry)
-                has_error_dx = self.current_dataset.dx is not None
-                has_error_dy = self.current_dataset.dy is not None
-                self.remove_empty_q_values(has_error_dx=has_error_dx,
-                    has_error_dy=has_error_dy)
-                self.send_to_output() # Combine datasets with DataInfo
-                self.current_datainfo = DataInfo() # Reset DataInfo
+                self.data_cleanup()
         except FileContentsException as fc_exc:
             # File doesn't meet schema - try loading with a less strict schema
@@ -154,6 +149,7 @@
                     self.load_file_and_schema(xml_file) # Reload strict schema so we can find where error are in file
                     invalid_xml = self.find_invalid_xml()
-                    invalid_xml = INVALID_XML.format(basename + self.extension) + invalid_xml
-                    raise DataReaderException(invalid_xml) # Handled by base class
+                    if invalid_xml != "":
+                        invalid_xml = INVALID_XML.format(basename + self.extension) + invalid_xml
+                        raise DataReaderException(invalid_xml) # Handled by base class
                 except FileContentsException as fc_exc:
                     msg = "CanSAS Reader could not load the file {}".format(xml_file)
@@ -279,30 +275,16 @@
                 # I and Q points
                 elif tagname == 'I' and isinstance(self.current_dataset, plottable_1D):
-                    unit_list = unit.split("|")
-                    if len(unit_list) > 1:
-                        self.current_dataset.yaxis(unit_list[0].strip(),
-                                                   unit_list[1].strip())
-                    else:
-                        self.current_dataset.yaxis("Intensity", unit)
+                    self.current_dataset.yaxis("Intensity", unit)
                     self.current_dataset.y = np.append(self.current_dataset.y, data_point)
                 elif tagname == 'Idev' and isinstance(self.current_dataset, plottable_1D):
                     self.current_dataset.dy = np.append(self.current_dataset.dy, data_point)
                 elif tagname == 'Q':
-                    unit_list = unit.split("|")
-                    if len(unit_list) > 1:
-                        self.current_dataset.xaxis(unit_list[0].strip(),
-                                                   unit_list[1].strip())
-                    else:
-                        self.current_dataset.xaxis("Q", unit)
+                    self.current_dataset.xaxis("Q", unit)
                     self.current_dataset.x = np.append(self.current_dataset.x, data_point)
                 elif tagname == 'Qdev':
                     self.current_dataset.dx = np.append(self.current_dataset.dx, data_point)
                 elif tagname == 'dQw':
-                    if self.current_dataset.dxw is None:
-                        self.current_dataset.dxw = np.empty(0)
-                    self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point)
+                   self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point)
                 elif tagname == 'dQl':
-                    if self.current_dataset.dxl is None:
-                        self.current_dataset.dxl = np.empty(0)
                     self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point)
                 elif tagname == 'Qmean':
@@ -312,4 +294,8 @@
                 elif tagname == 'Sesans':
                     self.current_datainfo.isSesans = bool(data_point)
+                    self.current_dataset.xaxis(attr.get('x_axis'),
+                                                attr.get('x_unit'))
+                    self.current_dataset.yaxis(attr.get('y_axis'),
+                                                attr.get('y_unit'))
                 elif tagname == 'yacceptance':
                     self.current_datainfo.sample.yacceptance = (data_point, unit)
@@ -512,8 +498,26 @@
             for error in self.errors:
                 self.current_datainfo.errors.add(error)
-            self.errors.clear()
-            self.send_to_output()
+            self.data_cleanup()
+            self.sort_one_d_data()
+            self.sort_two_d_data()
+            self.reset_data_list()
             empty = None
             return self.output[0], empty
+
+    def data_cleanup(self):
+        """
+        Clean up the data sets and refresh everything
+        :return: None
+        """
+        has_error_dx = self.current_dataset.dx is not None
+        has_error_dxl = self.current_dataset.dxl is not None
+        has_error_dxw = self.current_dataset.dxw is not None
+        has_error_dy = self.current_dataset.dy is not None
+        self.remove_empty_q_values(has_error_dx=has_error_dx,
+                                   has_error_dxl=has_error_dxl,
+                                   has_error_dxw=has_error_dxw,
+                                   has_error_dy=has_error_dy)
+        self.send_to_output()  # Combine datasets with DataInfo
+        self.current_datainfo = DataInfo()  # Reset DataInfo
 
     def _is_call_local(self):
@@ -642,8 +646,11 @@
                     value_unit = local_unit
             except KeyError:
-                err_msg = "CanSAS reader: unexpected "
-                err_msg += "\"{0}\" unit [{1}]; "
-                err_msg = err_msg.format(tagname, local_unit)
-                err_msg += "expecting [{0}]".format(default_unit)
+                # Do not throw an error for loading Sesans data in cansas xml
+                # This is a temporary fix.
+                if local_unit != "A" and local_unit != 'pol':
+                    err_msg = "CanSAS reader: unexpected "
+                    err_msg += "\"{0}\" unit [{1}]; "
+                    err_msg = err_msg.format(tagname, local_unit)
+                    err_msg += "expecting [{0}]".format(default_unit)
                 value_unit = local_unit
             except:
@@ -675,17 +682,15 @@
             di_exists = True
         if dqw_exists and not dql_exists:
-            array_size = self.current_dataset.dxw.size - 1
-            self.current_dataset.dxl = np.append(self.current_dataset.dxl,
-                                                 np.zeros([array_size]))
+            array_size = self.current_dataset.dxw.size
+            self.current_dataset.dxl = np.zeros(array_size)
         elif dql_exists and not dqw_exists:
-            array_size = self.current_dataset.dxl.size - 1
-            self.current_dataset.dxw = np.append(self.current_dataset.dxw,
-                                                 np.zeros([array_size]))
+            array_size = self.current_dataset.dxl.size
+            self.current_dataset.dxw = np.zeros(array_size)
         elif not dql_exists and not dqw_exists and not dq_exists:
-            array_size = self.current_dataset.x.size - 1
+            array_size = self.current_dataset.x.size
             self.current_dataset.dx = np.append(self.current_dataset.dx,
                                                 np.zeros([array_size]))
         if not di_exists:
-            array_size = self.current_dataset.y.size - 1
+            array_size = self.current_dataset.y.size
             self.current_dataset.dy = np.append(self.current_dataset.dy,
                                                 np.zeros([array_size]))
@@ -857,27 +862,31 @@
             node.append(point)
             self.write_node(point, "Q", datainfo.x[i],
-                            {'unit': datainfo._xaxis + " | " + datainfo._xunit})
+                            {'unit': datainfo.x_unit})
             if len(datainfo.y) >= i:
                 self.write_node(point, "I", datainfo.y[i],
-                                {'unit': datainfo._yaxis + " | " + datainfo._yunit})
+                                {'unit': datainfo.y_unit})
             if datainfo.dy is not None and len(datainfo.dy) > i:
                 self.write_node(point, "Idev", datainfo.dy[i],
-                                {'unit': datainfo._yaxis + " | " + datainfo._yunit})
+                                {'unit': datainfo.y_unit})
             if datainfo.dx is not None and len(datainfo.dx) > i:
                 self.write_node(point, "Qdev", datainfo.dx[i],
-                                {'unit': datainfo._xaxis + " | " + datainfo._xunit})
+                                {'unit': datainfo.x_unit})
             if datainfo.dxw is not None and len(datainfo.dxw) > i:
                 self.write_node(point, "dQw", datainfo.dxw[i],
-                                {'unit': datainfo._xaxis + " | " + datainfo._xunit})
+                                {'unit': datainfo.x_unit})
             if datainfo.dxl is not None and len(datainfo.dxl) > i:
                 self.write_node(point, "dQl", datainfo.dxl[i],
-                                {'unit': datainfo._xaxis + " | " + datainfo._xunit})
+                                {'unit': datainfo.x_unit})
         if datainfo.isSesans:
-            sesans = self.create_element("Sesans")
+            sesans_attrib = {'x_axis': datainfo._xaxis,
+                             'y_axis': datainfo._yaxis,
+                             'x_unit': datainfo.x_unit,
+                             'y_unit': datainfo.y_unit}
+            sesans = self.create_element("Sesans", attrib=sesans_attrib)
             sesans.text = str(datainfo.isSesans)
-            node.append(sesans)
-            self.write_node(node, "yacceptance", datainfo.sample.yacceptance[0],
+            entry_node.append(sesans)
+            self.write_node(entry_node, "yacceptance", datainfo.sample.yacceptance[0],
                              {'unit': datainfo.sample.yacceptance[1]})
-            self.write_node(node, "zacceptance", datainfo.sample.zacceptance[0],
+            self.write_node(entry_node, "zacceptance", datainfo.sample.zacceptance[0],
                              {'unit': datainfo.sample.zacceptance[1]})
 
Index: src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py
===================================================================
--- src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py	(revision dcb91cf83e474bdbe1c788d87690ca5f5e7841cb)
+++ src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py	(revision c9ecd1b562e38798001341ea1382b347f0cc1af9)
@@ -140,4 +140,5 @@
 
             if isinstance(value, h5py.Group):
+                # Set parent class before recursion
                 self.parent_class = class_name
                 parent_list.append(key)
@@ -150,4 +151,6 @@
                 # Recursion step to access data within the group
                 self.read_children(value, parent_list)
+                # Reset parent class when returning from recursive method
+                self.parent_class = class_name
                 self.add_intermediate()
                 parent_list.remove(key)
Index: src/sas/sascalc/dataloader/readers/xml_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/xml_reader.py	(revision fafe52a82bebe8d8a20bfb820388c964aa3c4b7b)
+++ src/sas/sascalc/dataloader/readers/xml_reader.py	(revision fafe52a82bebe8d8a20bfb820388c964aa3c4b7b)
@@ -134,4 +134,7 @@
             first_error = schema.assertValid(self.xmldoc)
         except etree.DocumentInvalid as err:
+            # Suppress errors for <'any'> elements
+            if "##other" in str(err):
+                return first_error
             first_error = str(err)
         return first_error
Index: src/sas/sascalc/invariant/invariant.py
===================================================================
--- src/sas/sascalc/invariant/invariant.py	(revision 7432acb919f4013119ca918a73350297e0d4c93f)
+++ src/sas/sascalc/invariant/invariant.py	(revision b1f20d17802efab479556ccd4fab9ef91f08b7bb)
@@ -610,5 +610,5 @@
         # Data boundaries for fitting
         qmin = self._data.x[0]
-        qmax = self._data.x[self._low_extrapolation_npts - 1]
+        qmax = self._data.x[int(self._low_extrapolation_npts - 1)]
 
         # Extrapolate the low-Q data
@@ -649,6 +649,6 @@
         # Data boundaries for fitting
         x_len = len(self._data.x) - 1
-        qmin = self._data.x[x_len - (self._high_extrapolation_npts - 1)]
-        qmax = self._data.x[x_len]
+        qmin = self._data.x[int(x_len - (self._high_extrapolation_npts - 1))]
+        qmax = self._data.x[int(x_len)]
 
         # fit the data with a model to get the appropriate parameters
@@ -688,5 +688,5 @@
         if npts_in is None:
             npts_in = self._low_extrapolation_npts
-        q_end = self._data.x[max(0, npts_in - 1)]
+        q_end = self._data.x[max(0, int(npts_in - 1))]
 
         if q_start >= q_end:
@@ -714,7 +714,7 @@
         # Get extrapolation range
         if npts_in is None:
-            npts_in = self._high_extrapolation_npts
+            npts_in = int(self._high_extrapolation_npts)
         _npts = len(self._data.x)
-        q_start = self._data.x[min(_npts, _npts - npts_in)]
+        q_start = self._data.x[min(_npts, int(_npts - npts_in))]
 
         if q_start >= q_end:
Index: src/sas/sasgui/guiframe/config.py
===================================================================
--- src/sas/sasgui/guiframe/config.py	(revision a1b8fee73528559155793dd74cda07d0c32e9d72)
+++ src/sas/sasgui/guiframe/config.py	(revision d9089328dec4c154a6bac2735e52b5e6fb3c8af2)
@@ -48,5 +48,5 @@
 '''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.'''
 _acknowledgement_citation = \
-'''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138'''
+'''M. Doucet et al. SasView Version 4.1.2, Zenodo, 10.5281/zenodo.825675'''
 
 _acknowledgement =  \
Index: src/sas/sasgui/guiframe/documentation_window.py
===================================================================
--- src/sas/sasgui/guiframe/documentation_window.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ src/sas/sasgui/guiframe/documentation_window.py	(revision d7ee5866aee5ca0454680f4e0503503702611c72)
@@ -75,9 +75,13 @@
             logger.error("Could not find Sphinx documentation at %s \
             -- has it been built?", file_path)
-        elif WX_SUPPORTS_HTML2:
-            # Complete HTML/CSS support!
-            self.view = html.WebView.New(self)
-            self.view.LoadURL(url)
-            self.Show()
+        #Commenting following 5 lines, so default browser is forced
+        #This is due to CDN mathjax discontinuation of service, intenal help
+        #browser should be back with qt version
+        #Note added by Wojtek Potrzebowski, July 4th 2017
+        # elif WX_SUPPORTS_HTML2:
+        #     # Complete HTML/CSS support!
+        #     self.view = html.WebView.New(self)
+        #     self.view.LoadURL(url)
+        #     self.Show()
         else:
             logger.error("No html2 support, popping up a web browser")
Index: src/sas/sasgui/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 79e6a33e39a965552e3c863cc0b90d3d34b281c0)
+++ src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 79e6a33e39a965552e3c863cc0b90d3d34b281c0)
@@ -1243,8 +1243,12 @@
             wx.PostEvent(self.parent, new_event)
             # update list of plugins if new plugin is available
-            custom_model = CUSTOM_MODEL
             mod_cat = self.categorybox.GetStringSelection()
-            if mod_cat == custom_model:
+            if mod_cat == CUSTOM_MODEL:
+                temp_id = self.model.id
                 temp = self.parent.update_model_list()
+                for v in self.parent.model_dictionary.values():
+                    if v.id == temp_id:
+                        self.model = v()
+                        break
                 if temp:
                     self.model_list_box = temp
Index: src/sas/sasgui/perspectives/fitting/fitpanel.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpanel.py	(revision 6f9abd39b6d696038bf298ef8e8b277439a2cb9c)
+++ src/sas/sasgui/perspectives/fitting/fitpanel.py	(revision c9ecd1b562e38798001341ea1382b347f0cc1af9)
@@ -92,11 +92,17 @@
             # state must be cloned
             state = page.get_state().clone()
-            if data is not None or page.model is not None:
+            # data_list only populated with real data
+            # Fake object in data from page.get_data() if model is selected
+            if len(page.data_list) is not 0 and page.model is not None:
                 new_doc = self._manager.state_reader.write_toXML(data,
                                                                  state,
                                                                  batch_state)
+                # Fit #2 through #n are append to first fit
                 if doc is not None and hasattr(doc, "firstChild"):
-                    child = new_doc.firstChild.firstChild
-                    doc.firstChild.appendChild(child)
+                    # Only append if properly formed new_doc
+                    if new_doc is not None and hasattr(new_doc, "firstChild"):
+                        child = new_doc.firstChild.firstChild
+                        doc.firstChild.appendChild(child)
+                # First fit defines the main document
                 else:
                     doc = new_doc
@@ -395,8 +401,5 @@
                 temp_data = page.get_data()
                 if temp_data is not None and temp_data.id in data:
-                    self.SetSelection(pos)
-                    self.on_close_page(event=None)
-                    temp = self.GetSelection()
-                    self.DeletePage(temp)
+                    self.close_page_with_data(temp_data)
             if self.sim_page is not None:
                 if len(self.sim_page.model_list) == 0:
@@ -404,6 +407,5 @@
                     self.SetSelection(pos)
                     self.on_close_page(event=None)
-                    temp = self.GetSelection()
-                    self.DeletePage(temp)
+                    self.DeletePage(pos)
                     self.sim_page = None
                     self.batch_on = False
Index: src/sas/sasgui/perspectives/fitting/models.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/models.py	(revision 632fda90d2ac7346a8a5e823a4e5ad1fff44b05f)
+++ src/sas/sasgui/perspectives/fitting/models.py	(revision 632fda90d2ac7346a8a5e823a4e5ad1fff44b05f)
@@ -21,4 +21,5 @@
 from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller
 from sasmodels.sasview_model import load_custom_model, load_standard_models
+from sas.sasgui.perspectives.fitting.fitpage import CUSTOM_MODEL
 
 logger = logging.getLogger(__name__)
@@ -266,5 +267,7 @@
         temp = {}
         if self.is_changed():
-            return  _find_models()
+            temp =  _find_models()
+            self.last_time_dir_modified = time.time()
+            return temp
         logger.info("plugin model : %s" % str(temp))
         return temp
@@ -323,5 +326,5 @@
         if os.path.isdir(plugin_dir):
             temp = os.path.getmtime(plugin_dir)
-            if  self.last_time_dir_modified != temp:
+            if  self.last_time_dir_modified < temp:
                 is_modified = True
                 self.last_time_dir_modified = temp
@@ -334,12 +337,12 @@
         new models were added else return empty dictionary
         """
+        self.plugins = []
         new_plugins = self.findModels()
-        if len(new_plugins) > 0:
-            for name, plug in  new_plugins.iteritems():
-                if name not in self.stored_plugins.keys():
-                    self.stored_plugins[name] = plug
-                    self.plugins.append(plug)
-                    self.model_dictionary[name] = plug
-            self.model_combobox.set_list("Plugin Models", self.plugins)
+        if new_plugins:
+            for name, plug in  new_plugins.items():
+                self.stored_plugins[name] = plug
+                self.plugins.append(plug)
+                self.model_dictionary[name] = plug
+            self.model_combobox.set_list(CUSTOM_MODEL, self.plugins)
             return self.model_combobox.get_list()
         else:
Index: src/sas/sasgui/perspectives/fitting/pagestate.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/pagestate.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ src/sas/sasgui/perspectives/fitting/pagestate.py	(revision da9b23921df41d99e3b43e2bba26803e24afece2)
@@ -617,4 +617,6 @@
             value = ""
             content = line.split(":")
+            if line == '' or len(content) == 1:
+                continue
             name = content[0]
             try:
Index: test/sasdataloader/test/utest_abs_reader.py
===================================================================
--- test/sasdataloader/test/utest_abs_reader.py	(revision a78a02fe90f1c962f523301685c143a27f11ba7d)
+++ test/sasdataloader/test/utest_abs_reader.py	(revision ae69c690bae8eb1cae0c6902dd71755dda9710f8)
@@ -333,5 +333,4 @@
         self.assertEqual(self.data.x[1], 0.03)
         self.assertAlmostEquals(self.data.y[1], 1001.0)
-        self.assertEqual(self.data.dx[0], 0.0)
         self.assertEqual(self.data.dxl[1], 0.005)
         self.assertEqual(self.data.dxw[1], 0.001)
