Index: src/sas/sasgui/guiframe/CategoryInstaller.py
===================================================================
--- src/sas/sasgui/guiframe/CategoryInstaller.py	(revision 50008e349254372d579f42bb3ad653d593d7a40b)
+++ src/sas/sasgui/guiframe/CategoryInstaller.py	(revision 212bfc297ca102b648c949f030d3d06a4c569fa3)
@@ -11,7 +11,7 @@
 import os
 import sys
-import shutil
 import json
-from collections import defaultdict
+import logging
+from collections import defaultdict, OrderedDict
 
 USER_FILE = 'categories.json'
@@ -23,5 +23,4 @@
     Note - class is entirely static!
     """
-
 
     def __init__(self):
@@ -43,5 +42,5 @@
         import sas.sasgui.perspectives.fitting.models
         return sas.sasgui.perspectives.fitting.models.get_model_python_path()
-    
+
     @staticmethod
     def _get_default_cat_file_dir():
@@ -54,5 +53,5 @@
         import sas.sasview
         cat_file = "default_categories.json"
-        
+
         possible_cat_file_paths = [
             os.path.join(os.path.split(sas.sasview.__file__)[0], cat_file),           # Source
@@ -64,5 +63,5 @@
             if os.path.isfile(path):
                 return os.path.dirname(path)
-            
+
         raise RuntimeError('CategoryInstaller: Could not find folder containing default categories')
 
@@ -89,7 +88,6 @@
                 by_model_dict[model].append(category)
                 model_enabled_dict[model] = enabled
-    
+
         return (by_model_dict, model_enabled_dict)
-
 
     @staticmethod
@@ -105,6 +103,5 @@
                 master_category_dict[category].append(\
                     (model, model_enabled_dict[model]))
-        
-        return master_category_dict
+        return OrderedDict(sorted(master_category_dict.items(), key=lambda t: t[0]))
 
     @staticmethod
@@ -113,16 +110,10 @@
         returns the user data file, eg .sasview/categories.json.json
         """
-        return os.path.join(CategoryInstaller._get_home_dir(),
-                            USER_FILE)
+        return os.path.join(CategoryInstaller._get_home_dir(), USER_FILE)
 
     @staticmethod
     def get_default_file():
-        """
-        returns the path of the default file
-        e.g. blahblah/default_categories.json
-        """
-        return os.path.join(\
-            CategoryInstaller._get_default_cat_file_dir(), "default_categories.json")
-        
+        logging.warning("CategoryInstaller.get_default_file is deprecated.")
+
     @staticmethod
     def check_install(homedir = None, model_list=None):
@@ -134,8 +125,8 @@
         :param model_list: List of model names except customized models
         """
-        #model_list = []
-        default_file = CategoryInstaller.get_default_file()
+        _model_dict = { model.name: model for model in model_list}
+        _model_list = _model_dict.keys()
+
         serialized_file = None
-        master_category_dict = defaultdict(list)
         if homedir == None:
             serialized_file = CategoryInstaller.get_user_file()
@@ -143,18 +134,17 @@
             serialized_file = os.path.join(homedir, USER_FILE)
         if os.path.isfile(serialized_file):
-            cat_file = open(serialized_file, 'rb')
+            with open(serialized_file, 'rb') as f:
+                master_category_dict = json.load(f)
         else:
-            cat_file = open(default_file, 'rb')
-        master_category_dict = json.load(cat_file)
-#        master_category_dict = pickle.Unpickler(cat_file).load()
+            master_category_dict = defaultdict(list)
+
         (by_model_dict, model_enabled_dict) = \
                 CategoryInstaller._regenerate_model_dict(master_category_dict)
-        cat_file.close()
-        add_list = model_list
+        add_list = _model_list
         del_name = False
         for cat in master_category_dict.keys():
             for ind in range(len(master_category_dict[cat])):
                 model_name, enabled = master_category_dict[cat][ind]
-                if model_name not in model_list:
+                if model_name not in _model_list:
                     del_name = True 
                     try:
@@ -162,5 +152,5 @@
                         model_enabled_dict.pop(model_name)
                     except:
-                        pass
+                        logging.error("CategoryInstaller: %s", sys.exc_value)
                 else:
                     add_list.remove(model_name)
@@ -168,10 +158,19 @@
             for model in add_list:
                 model_enabled_dict[model]= True
-                by_model_dict[model].append('Uncategorized')
-    
+                if _model_dict[model].category is None or len(str(_model_dict[model].category.capitalize())) == 0:
+                    by_model_dict[model].append('Uncategorized')
+                else:
+                    category = _model_dict[model].category
+                    toks = category.split(':')
+                    category = toks[-1]
+                    toks = category.split('-')
+                    capitalized_words = [t.capitalize() for t in toks]
+                    category = ' '.join(capitalized_words)
+
+                    by_model_dict[model].append(category)
+
             master_category_dict = \
                 CategoryInstaller._regenerate_master_dict(by_model_dict,
                                                           model_enabled_dict)
-            
-            json.dump( master_category_dict,
-                         open(serialized_file, 'wb') )
+
+            json.dump(master_category_dict, open(serialized_file, 'wb'))
Index: src/sas/sasgui/guiframe/CategoryManager.py
===================================================================
--- src/sas/sasgui/guiframe/CategoryManager.py	(revision 80b1df3a323cc6cd02a52c2e6e711def31b0024c)
+++ src/sas/sasgui/guiframe/CategoryManager.py	(revision 212bfc297ca102b648c949f030d3d06a4c569fa3)
@@ -13,4 +13,5 @@
 import sys
 import os
+import logging
 from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
 from collections import defaultdict
@@ -366,17 +367,11 @@
         """
         try:
-            file = CategoryInstaller.get_user_file()
-            if os.path.isfile(file):
-                cat_file = open(file, 'rb')
-#               self.master_category_dict = pickle.load(cat_file)
-                self.master_category_dict = json.load(cat_file)
-            else:
-                cat_file = open(CategoryInstaller.get_default_file(), 'rb')
-#        		self.master_category_dict = pickle.load(cat_file)
-                self.master_category_dict = json.load(cat_file)
-            cat_file.close()
+            cat_file = CategoryInstaller.get_user_file()
+            self.master_category_dict = {}
+            if os.path.isfile(cat_file):
+                with open(cat_file, 'rb') as f:
+                    self.master_category_dict = json.load(f)
         except IOError:
-            print 'Problem reading in category file. Please review'
-
+            logging.error('Problem reading in category file.')
 
         self._regenerate_model_dict()
Index: src/sas/sasgui/guiframe/customdir.py
===================================================================
--- src/sas/sasgui/guiframe/customdir.py	(revision d85c194ea2f78cb2b9b3de9c969e1b8ebea6b6d2)
+++ src/sas/sasgui/guiframe/customdir.py	(revision 212bfc297ca102b648c949f030d3d06a4c569fa3)
@@ -1,7 +1,5 @@
 # Setup and find Custom config dir
-import sys
 import os.path
 import shutil
-from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller
 
 CONF_DIR = 'config' 
@@ -12,7 +10,5 @@
     Find and return user/.sasview dir
     """
-    dir = os.path.join(os.path.expanduser("~"), 
-                       ("." + APPLICATION_NAME))
-    return dir
+    return os.path.join(os.path.expanduser("~"), ("." + APPLICATION_NAME))
 
 def _find_customconf_dir():
@@ -22,7 +18,5 @@
     """
     u_dir = _find_usersasview_dir()
-    dir = os.path.join(u_dir, CONF_DIR)
-    
-    return dir
+    return os.path.join(u_dir, CONF_DIR)
 
 def _setup_conf_dir(path):
@@ -30,26 +24,14 @@
     Setup the custom config dir and cat file
     """
-    dir = _find_customconf_dir()
+    conf_dir = _find_customconf_dir()
     # If the plugin directory doesn't exist, create it
-    if not os.path.isdir(dir):
-        os.makedirs(dir)
-    file = os.path.join(dir, "custom_config.py")
-    cat_file = CategoryInstaller.get_user_file()
-    # If the user category file doesn't exist copy the default to
-    # the user directory
-    if not os.path.isfile(cat_file):
-        try:
-            default_cat_file = CategoryInstaller.get_default_file()
-            if os.path.isfile(default_cat_file):
-                shutil.copyfile(default_cat_file, cat_file)
-            else:
-                print "Unable to find/copy default cat file"
-        except:
-            print "Unable to copy default cat file to the user dir."
+    if not os.path.isdir(conf_dir):
+        os.makedirs(conf_dir)
+    config_file = os.path.join(conf_dir, "custom_config.py")
 
     # Place example user models as needed
     try:
-        if not os.path.isfile(file):
-         shutil.copyfile(os.path.join(path, "custom_config.py"), file)
+        if not os.path.isfile(config_file):
+            shutil.copyfile(os.path.join(path, "custom_config.py"), config_file)
     except:
         # Check for data path next to exe/zip file.
@@ -63,13 +45,12 @@
             temp_path = os.path.join(f_dir, "custom_config.py")
             if os.path.isfile(temp_path):
-                shutil.copyfile(temp_path, file)
+                shutil.copyfile(temp_path, config_file)
                 is_dir = True
                 break
         if not is_dir:
             raise
-        
-    return dir
-  
-        
+    return conf_dir
+
+
 class SetupCustom(object):
     """
@@ -81,7 +62,2 @@
     def setup_dir(self, path):
         return _setup_conf_dir(path)
-    
-
-    
-    
-  
Index: src/sas/sasgui/guiframe/dataFitting.py
===================================================================
--- src/sas/sasgui/guiframe/dataFitting.py	(revision 79885018e2047aef9517748c8de7eccc28d1305e)
+++ src/sas/sasgui/guiframe/dataFitting.py	(revision 79885018e2047aef9517748c8de7eccc28d1305e)
@@ -378,73 +378,5 @@
         _str = "%s\n" % LoadData2D.__str__(self)
         return _str 
-    
-    def _validity_check(self, other):
-        """
-        Checks that the data lengths are compatible.
-        Checks that the x vectors are compatible.
-        Returns errors vectors equal to original
-        errors vectors if they were present or vectors
-        of zeros when none was found.
-        
-        :param other: other data set for operation
-        
-        :return: dy for self, dy for other [numpy arrays]
-        
-        :raise ValueError: when lengths are not compatible
-        
-        """
-        err_other = None
-        if isinstance(other, Data2D):
-            # Check that data lengths are the same
-            if len(self.data) != len(other.data) or \
-                len(self.qx_data) != len(other.qx_data) or \
-                len(self.qy_data) != len(other.qy_data):
-                msg = "Unable to perform operation: data length are not equal"
-                raise ValueError, msg
-            #if len(self.data) < 1:
-            #    msg = "Incompatible data sets: I-values do not match"
-            #    raise ValueError, msg 
-            for ind in range(len(self.data)):
-                if self.qx_data[ind] != other.qx_data[ind]:
-                    msg = "Incompatible data sets: qx-values do not match"
-                    raise ValueError, msg
-                if self.qy_data[ind] != other.qy_data[ind]:
-                    msg = "Incompatible data sets: qy-values do not match"
-                    raise ValueError, msg
-                   
-            # Check that the scales match
-            err_other = other.err_data
-            if other.err_data == None or \
-                (len(other.err_data) != len(other.data)):
-                err_other = numpy.zeros(len(other.data))
-            
-        # Check that we have errors, otherwise create zero vector
-        err = self.err_data
-        if self.err_data == None or \
-            (len(self.err_data) != len(self.data)):
-            err = numpy.zeros(len(other.data))
-            
-        return err, err_other
-
-    def _validity_check_union(self, other):
-        """
-        Checks that the data lengths are compatible.
-        Checks that the x vectors are compatible.
-        Returns errors vectors equal to original
-        errors vectors if they were present or vectors
-        of zeros when none was found.
-        
-        :param other: other data set for operation
-        
-        :return: bool
-        
-        :raise ValueError: when data types are not compatible
-        
-        """
-        if not isinstance(other, Data2D):
-            msg = "Unable to perform operation: different types of data set"
-            raise ValueError, msg   
-        return True
-    
+
     def _perform_operation(self, other, operation):
         """
Index: src/sas/sasgui/guiframe/data_panel.py
===================================================================
--- src/sas/sasgui/guiframe/data_panel.py	(revision e767897d6a10f25bfe2bccbef3e3fe6ab0385f7c)
+++ src/sas/sasgui/guiframe/data_panel.py	(revision 998ca90ad87500d7d5fb3f4eb13105752a2f2952)
@@ -890,14 +890,15 @@
 
 
-    def on_remove(self, event):
+    def on_remove(self, event, msg=""):
         """
         Get a list of item checked and remove them from the treectrl
         Ask the parent to remove reference to this item
         """
-        msg = "This operation will delete the data sets checked "
-        msg += "and all the dependents."
+        if msg == "":
+            msg = "This operation will delete the data sets checked "
+            msg += "and all the dependents."
         msg_box = wx.MessageDialog(None, msg, 'Warning', wx.OK|wx.CANCEL)
         if msg_box.ShowModal() != wx.ID_OK:
-            return
+            return True
 
         data_to_remove, theory_to_remove, _ = self.set_data_helper()
Index: src/sas/sasgui/guiframe/gui_manager.py
===================================================================
--- src/sas/sasgui/guiframe/gui_manager.py	(revision 3fac0df814fa16cb4e81b12f38998515162dd09a)
+++ src/sas/sasgui/guiframe/gui_manager.py	(revision a4c24459af9d908f923d5abb9809c6744530b90c)
@@ -677,24 +677,27 @@
         update edit menu if available
         """
-        if event != None:
+        if event is not None:
             self.panel_on_focus = event.panel
         if self.panel_on_focus is not None:
-            #Disable save application if the current panel is in batch mode
-            flag = self.panel_on_focus.get_save_flag()
-            if self._save_appl_menu != None:
-                self._save_appl_menu.Enable(flag)
-
-            if self.panel_on_focus not in self.plot_panels.values():
-                for ID in self.panels.keys():
-                    if self.panel_on_focus != self.panels[ID]:
-                        self.panels[ID].on_kill_focus(None)
-
-            if self._data_panel is not None and \
-                            self.panel_on_focus is not None:
-                self.set_panel_on_focus_helper()
-                #update toolbar
-                self._update_toolbar_helper()
-                #update edit menu
-                self.enable_edit_menu()
+            # Disable save application if the current panel is in batch mode
+            try:
+                flag = self.panel_on_focus.get_save_flag()
+                if self._save_appl_menu != None:
+                    self._save_appl_menu.Enable(flag)
+
+                if self.panel_on_focus not in self.plot_panels.values():
+                    for ID in self.panels.keys():
+                        if self.panel_on_focus != self.panels[ID]:
+                            self.panels[ID].on_kill_focus(None)
+
+                if self._data_panel is not None and \
+                                self.panel_on_focus is not None:
+                    self.set_panel_on_focus_helper()
+                    #update toolbar
+                    self._update_toolbar_helper()
+                    #update edit menu
+                    self.enable_edit_menu()
+            except wx._core.PyDeadObjectError:
+                pass
 
     def disable_app_menu(self, p_panel=None):
@@ -1152,5 +1155,6 @@
                 self.delete_panel(ID)
                 break
-        self.cpanel_on_focus.SetFocus()
+        if self.cpanel_on_focus is not None:
+            self.cpanel_on_focus.SetFocus()
 
 
@@ -1333,4 +1337,11 @@
                     self._applications_menu_name = name
 
+    def _on_marketplace_click(self, event):
+        """
+            Click event for the help menu item linking to the Marketplace.
+        """
+        import webbrowser
+        webbrowser.open_new(config.marketplace_url)
+
     def _add_help_menu(self):
         """
@@ -1338,12 +1349,9 @@
         tutorial PDF and documentation pages.
         """
-        # Help menu
         self._help_menu = wx.Menu()
-        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
 
         wx_id = wx.NewId()
         self._help_menu.Append(wx_id, '&Documentation', '')
         wx.EVT_MENU(self, wx_id, self._onSphinxDocs)
-        self._help_menu.AppendSeparator()
 
         if config._do_tutorial and (IS_WIN or sys.platform == 'darwin'):
@@ -1351,6 +1359,4 @@
             self._help_menu.Append(wx_id, '&Tutorial', 'Software tutorial')
             wx.EVT_MENU(self, wx_id, self._onTutorial)
-            self._help_menu.AppendSeparator()
-
 
         if config._do_acknowledge:
@@ -1358,6 +1364,4 @@
             self._help_menu.Append(wx_id, '&Acknowledge', 'Acknowledging SasView')
             wx.EVT_MENU(self, wx_id, self._onAcknowledge)
-            self._help_menu.AppendSeparator()
-
 
         if config._do_aboutbox:
@@ -1366,6 +1370,9 @@
             self._help_menu.Append(wx_id, '&About', 'Software information')
             wx.EVT_MENU(self, wx_id, self._onAbout)
-            self._help_menu.AppendSeparator()
-
+
+        if config.marketplace_url:
+            wx_id = wx.NewId()
+            self._help_menu.Append(wx_id, '&Model marketplace', '')
+            wx.EVT_MENU(self, wx_id, self._on_marketplace_click)
 
         # Checking for updates
@@ -1900,20 +1907,45 @@
     def _on_open_state_project(self, event):
         """
+        Load in a .svs project file after removing all data from SasView
         """
         path = None
         if self._default_save_location == None:
             self._default_save_location = os.getcwd()
-        wx.PostEvent(self, StatusEvent(status="Loading Project file..."))
-        dlg = wx.FileDialog(self,
+        msg = "This operation will set remove all data, plots and analyses from"
+        msg += " SasView before loading the project. Do you wish to continue?"
+        self._data_panel.selection_cbox.SetValue('Select all Data')
+        self._data_panel._on_selection_type(None)
+        for _, theory_dict in self._data_panel.list_cb_theory.iteritems():
+            for  key, value in theory_dict.iteritems():
+                item, _, _ = value
+                item.Check(True)
+        if not self._data_panel.on_remove(None, msg):
+            wx.PostEvent(self, StatusEvent(status="Loading Project file..."))
+            dlg = wx.FileDialog(self,
                             "Choose a file",
                             self._default_save_location, "",
                             APPLICATION_WLIST)
-        if dlg.ShowModal() == wx.ID_OK:
-            path = dlg.GetPath()
+            if dlg.ShowModal() == wx.ID_OK:
+                path = dlg.GetPath()
             if path is not None:
                 self._default_save_location = os.path.dirname(path)
-        dlg.Destroy()
-
-        self.load_state(path=path, is_project=True)
+                dlg.Destroy()
+                # Reset to a base state
+                self._on_reset_state()
+                # Load the project file
+                self.load_state(path=path, is_project=True)
+
+    def _on_reset_state(self):
+        """
+        Resets SasView to its freshly opened state.
+        :return: None
+        """
+        # Reset all plugins to their base state
+        self._data_panel.set_panel_on_focus()
+        # Remove all loaded data
+        for plugin in self.plugins:
+            plugin.clear_panel()
+        # Reset plot number to 0
+        self.graph_num = 0
 
     def _on_save_application(self, event):
@@ -2063,20 +2095,5 @@
             except:
                 logging.info("Failed to connect to www.sasview.org")
-        self._process_version(version_info, standalone=event == None)    
-
-        
-        
-#         
-#         try:
-#             req = urllib2.Request(config.__update_URL__)
-#             res = urllib2.urlopen(req)
-#             content = res.read().strip()
-#             logging.info("Connected to www.sasview.org. Latest version: %s"
-#                          % (content))
-#             version_info = json.loads(content)
-#         except:
-#             logging.info("Failed to connect to www.sasview.org")
-#             version_info = {"version": "0.0.0"}
-#         self._process_version(version_info, standalone=event == None)
+        self._process_version(version_info, standalone=event == None)
 
     def _process_version(self, version_info, standalone=True):
Index: src/sas/sasgui/guiframe/media/data_formats_help.rst
===================================================================
--- src/sas/sasgui/guiframe/media/data_formats_help.rst	(revision 280f929c9b628eb5ce8a21b7a5072a29ccaec43a)
+++ src/sas/sasgui/guiframe/media/data_formats_help.rst	(revision 48b8f6d68e3c55ef89958eb0b7b56b22ea3d63d0)
@@ -10,22 +10,19 @@
 ============
 
-SasView reads several different 1D (I(Q) vs Q), 2D SANS(I(Qx,Qy) vs (Qx,Qy))
-and SESANS (P(z) vs z)
-data files. But please note that SasView does not at present load data where
-the Q and I(Q) data are in separate files.
+SasView reads several different 1D SAS (*I(Q) vs Q*), 2D SAS(*I(Qx,Qy) vs (Qx,Qy)*) and 1D SESANS (*P(z) vs z*) data files. From SasView 4.1 onwards, a :ref:`File_Converter_Tool` allows some legacy formats to be converted into modern formats that SasView will read.
 
-1D Formats SANS
----------------
+1D SAS Formats
+--------------
 
-SasView will read files with 2 to 4 columns of numbers in the following order: 
+SasView will read ASCII ('text') files with 2 to 4 columns of numbers in the following order: 
 
-    Q, I(Q), (dI(Q), dQ(Q))
+    *Q, I(Q), ( dI(Q), dQ(Q) )*
     
-where dQ(Q) is the instrumental resolution in Q and assumed to have originated 
+where *dQ(Q)* is the instrumental resolution in *Q* and assumed to have originated 
 from pinhole geometry.
 
 Numbers can be separated by spaces or commas.
 
-SasView recognises the following file extensions:
+SasView recognises the following file extensions which are not case-sensitive:
 
 *  .TXT
@@ -34,50 +31,65 @@
 *  .XML (in canSAS format v1.0 and 1.1)
 
-If using CSV output from, for example, a spreadsheet, ensure that it is not 
-using commas as delimiters for thousands.
+If using CSV output from, for example, a spreadsheet, ensure that it is not using commas as delimiters for thousands.
+
+The SasView :ref:`File_Converter_Tool` available in SasView 4.1 onwards can be used to convert data sets with separated *I(Q)* and *Q* files (for example, BSL/OTOKO, and some output from FIT2D and other SAXS-oriented software) into either the canSAS SASXML (XML) format or the NeXus NXcanSAS (HDF5) format.
 
 For a description of the CanSAS/SASXML format see:
 http://www.cansas.org/formats/canSAS1d/1.1/doc/
 
+For a description of the ISIS 1D format see:
+http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf
+
+For a description of the NXcanSAS format see:
+http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html
+
+All the above formats are written by the `Mantid Framework <http://www.mantidproject.org/>`_.
+
 For a description of the NIST 1D format see:
 http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_IQ
 
-For a description of the ISIS 1D format see:
-http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf
+For a description of the BSL/OTOKO format see: 
+http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html
 
 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
 
-2D Formats SANS
----------------
+2D SAS Formats
+--------------
 
-SasView will only read files in the NIST 2D format with the extensions 
-.ASC or .DAT
+SasView will read ASCII ('text') files in the NIST 2D format (with the extensions .ASC or .DAT) or files in the NeXus NXcanSAS (HDF5) format (with the extension .H5). File extensions are not case-sensitive. Both of these formats are written by the `Mantid Framework <http://www.mantidproject.org/>`_.
 
-Most of the header lines can be removed except the last line, and only the 
-first three columns (Qx, Qy, and I(Qx,Qy)) are actually required.
+Most of the header lines in the NIST 2D format can actually be removed except the last line, and only the first three columns (*Qx, Qy,* and *I(Qx,Qy)*) are actually required.
+
+The SasView :ref:`File_Converter_Tool` available in SasView 4.1 onwards can be used to convert data sets in the 2D BSL/OTOKO format into the NeXus NXcanSAS (HDF5) format.
 
 For a description of the NIST 2D format see:
 http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_2DQxQy 
 
-.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+For a description of the NXcanSAS format see: 
+http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html
 
-SESANS Format
--------------
-
-The current file extension is .ses or .sesans (not case sensitive).
-
-The file format is to have a list of name-value pairs as a header at the top of the file, detailing general experimental parameters necessary for fitting and analyzing data. This list should contain all information necessary for the file to be 'portable' between users.
-
-Following that is a 6 column list of instrument experimental variables:
-
-- Spin echo length (z, in Angstroms)
-- Spin echo length error (:math:`\Delta` z, in Angstroms) (experimental resolution)
-- neutron wavelength (:math:`\lambda`, in Angstroms) (essential for ToF instruments)
-- neutron wavelength error (:math:`\Delta \lambda`, in Angstroms)
-- Normalized polarization (:math:`P/P_0`, unitless)
-- Normalized polarization error (:math:`\Delta(P/P_0)`, unitless) (measurement error)
+For a description of the BSL/OTOKO format see: For a description of the BSL/OTOKO format see: 
+http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html
 
 
 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
 
-.. note::  This help document was last changed by Wim Bouwman, 05Oct2016
+1D SESANS Format
+----------------
+
+SasView version 4.1 onwards will read ASCII ('text') files in a prototype SESANS standard format (with the extensions .SES or .SESANS). The file extensions are not case-sensitive.
+
+The file format has a list of name-value pairs at the top of the file which detail the general experimental parameters necessary for fitting and analyzing data. This list should contain all the information necessary for the file to be 'portable' between users.
+
+Following the header is a 6 column list of instrument experimental variables:
+
+- Spin echo length (z, in Angstroms)
+- Spin echo length error (:math:`\Delta`\ z, in Angstroms) (experimental resolution)
+- Neutron wavelength (:math:`\lambda`, in Angstroms) (essential for ToF instruments)
+- Neutron wavelength error (:math:`\Delta \lambda`, in Angstroms)
+- Normalized polarization (:math:`P/P_0`, unitless)
+- Normalized polarization error (:math:`\Delta(P/P_0)`, unitless) (measurement error)
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+.. note::  This help document was last changed by Steve King, 07Oct2016
Index: src/sas/sasgui/guiframe/panel_base.py
===================================================================
--- src/sas/sasgui/guiframe/panel_base.py	(revision d85c194ea2f78cb2b9b3de9c969e1b8ebea6b6d2)
+++ src/sas/sasgui/guiframe/panel_base.py	(revision 18b7ecb9592132eb5e291874eb5b6c2046d54a45)
@@ -317,5 +317,14 @@
         """
         return self._drag_flag
-    
+
+    def _set_analysis(self, flag):
+        """
+        Set the Analysis Save state flag and informs the manager
+        so it refreshes the menu/whole panel
+        """
+        self._set_save_flag(flag)
+        if self._manager is not None:
+            wx.PostEvent(self._manager.parent, PanelOnFocusEvent(panel=self))
+
     def _set_reset_flag(self, flag=True):
         """
