"Fossies" - the Fresh Open Source Software Archive

Member "relax-5.0.0/gui/analyses/__init__.py" (6 Dec 2019, 25715 Bytes) of package /linux/privat/relax-5.0.0.src.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "__init__.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.3_vs_5.0.0.

    1 ###############################################################################
    2 #                                                                             #
    3 # Copyright (C) 2010-2015 Edward d'Auvergne                                   #
    4 #                                                                             #
    5 # This file is part of the program relax (http://www.nmr-relax.com).          #
    6 #                                                                             #
    7 # This program is free software: you can redistribute it and/or modify        #
    8 # it under the terms of the GNU General Public License as published by        #
    9 # the Free Software Foundation, either version 3 of the License, or           #
   10 # (at your option) any later version.                                         #
   11 #                                                                             #
   12 # This program is distributed in the hope that it will be useful,             #
   13 # but WITHOUT ANY WARRANTY; without even the implied warranty of              #
   14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
   15 # GNU General Public License for more details.                                #
   16 #                                                                             #
   17 # You should have received a copy of the GNU General Public License           #
   18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
   19 #                                                                             #
   20 ###############################################################################
   21 
   22 # Package docstring.
   23 """Package for the automatic and custom analysis GUI elements."""
   24 
   25 # Python module imports.
   26 import inspect
   27 import sys
   28 import wx
   29 
   30 # relax module imports.
   31 from data_store import Relax_data_store; ds = Relax_data_store()
   32 from data_store.gui import Gui
   33 import dep_check
   34 from gui.analyses.auto_model_free import Auto_model_free
   35 from gui.analyses.auto_noe import Auto_noe
   36 from gui.analyses.auto_r1 import Auto_r1
   37 from gui.analyses.auto_r2 import Auto_r2
   38 from gui.analyses.auto_relax_disp import Auto_relax_disp
   39 from gui.analyses.wizard import Analysis_wizard
   40 from gui.message import error_message, Question
   41 from lib.errors import RelaxError
   42 from pipe_control import pipes
   43 from pipe_control.reset import reset
   44 from status import Status; status = Status()
   45 
   46 
   47 # The package contents.
   48 __all__ = ['auto_model_free',
   49            'auto_noe',
   50            'auto_r1',
   51            'auto_r2',
   52            'auto_relax_disp',
   53            'auto_rx_base',
   54            'base',
   55            'elements',
   56            'relax_control',
   57            'results_analysis',
   58            'results']
   59 
   60 
   61 class Analysis_controller:
   62     """Class for controlling all aspects of analyses."""
   63 
   64     def __init__(self, gui):
   65         """Initialise the analysis controller.
   66 
   67         @param gui:         The gui object.
   68         @type gui:          wx object
   69         """
   70 
   71         # Store the args.
   72         self.gui = gui
   73 
   74         # Initialise some variables.
   75         self.init_state = True
   76         self._current = None
   77         self._num_analyses = 0
   78         self._switch_flag = True
   79 
   80         # The analyses page objects.
   81         self._analyses = []
   82 
   83         # Register the page switch method for pipe switches.
   84         self.name = 'notebook page switcher'
   85         status.observers.pipe_alteration.register(self.name, self.pipe_switch, method_name='pipe_switch')
   86 
   87         # Register a method for removing analyses if the associated pipe is deleted.
   88         status.observers.pipe_alteration.register('notebook pipe deletion', self.pipe_deletion, method_name='pipe_deletion')
   89 
   90         # Register the deletion of all analyses for the reset status observer.
   91         status.observers.reset.register('gui analyses', self.post_reset, method_name='post_reset')
   92 
   93         # Register state loading.
   94         status.observers.state_load.register('gui analyses', self.load_from_store, method_name='load_from_store')
   95 
   96 
   97     def analysis_data_loop(self):
   98         """Loop over the analyses, yielding the data objects.
   99 
  100         @return:    The analysis data object from the relax data store.
  101         @rtype:     data.gui.Analyses instance
  102         """
  103 
  104         # Loop over the analyses.
  105         for i in range(self._num_analyses):
  106             yield ds.relax_gui.analyses[i]
  107 
  108 
  109     def analysis_loop(self):
  110         """Loop over the analyses, yielding the page objects.
  111 
  112         @return:    The page object.
  113         @rtype:     wx.Frame object
  114         """
  115 
  116         # Loop over the analyses.
  117         for i in range(self._num_analyses):
  118             yield self._analyses[i]
  119 
  120 
  121     def current_data(self):
  122         """Return the data container of the current analysis from the relax data store.
  123 
  124         @return:    The data container of the current analysis.
  125         @rtype:     str
  126         """
  127 
  128         # No current page.
  129         if self._current == None:
  130             return
  131         if len(ds.relax_gui.analyses) == 0:
  132             return
  133 
  134         # Return the name.
  135         return ds.relax_gui.analyses[self._current]
  136 
  137 
  138     def current_analysis_name(self):
  139         """Return the name of the current analysis.
  140 
  141         @return:    The name of the current analysis.
  142         @rtype:     str
  143         """
  144 
  145         # No current page.
  146         if self._current == None:
  147             return
  148         if len(ds.relax_gui.analyses) == 0:
  149             return
  150 
  151         # Return the name.
  152         return ds.relax_gui.analyses[self._current].analysis_name
  153 
  154 
  155     def current_analysis_type(self):
  156         """Return the type of the current analysis.
  157 
  158         @return:    The type of the current analysis.
  159         @rtype:     str
  160         """
  161 
  162         # No current page.
  163         if self._current == None:
  164             return
  165         if len(ds.relax_gui.analyses) == 0:
  166             return
  167 
  168         # Return the name.
  169         return ds.relax_gui.analyses[self._current].analysis_type
  170 
  171 
  172     def delete_all(self, reset=False):
  173         """Remove all analyses."""
  174 
  175         # Debugging set up.
  176         if status.debug:
  177             fn_name = sys._getframe().f_code.co_name
  178             mod_name = inspect.getmodule(inspect.stack()[1][0]).__name__
  179             class_name = self.__class__.__name__
  180             full_name = "%s.%s.%s" % (mod_name, class_name, fn_name)
  181             print("\n\n")
  182             print("debug> %s:  Deleting all analyses." % full_name)
  183 
  184         # Unregister all observer objects prior to analysis deletion.  This is to prevent queued wx events being sent to dead or non-existent objects.
  185         if status.debug:
  186             print("debug> %s:  Unregistering all methods with the observer objects." % full_name)
  187         for i in range(self._num_analyses):
  188             self._analyses[i].observer_register(remove=True)
  189 
  190         # Delete the current tabs.
  191         while self._num_analyses:
  192             # Flush all pending events (bug fix for MS Windows).
  193             #wx.Yield()
  194 
  195             # Remove the last analysis, until there is nothing left.
  196             if status.debug:
  197                 print("debug> %s:  Deleting the analysis at index %s." % (full_name, self._num_analyses-1))
  198             self.delete_analysis(self._num_analyses-1, reset=reset)
  199 
  200         # Notify the observers of the change.
  201         if status.debug:
  202             print("debug> %s:  All analyses now deleted." % full_name)
  203         status.observers.gui_analysis.notify()
  204 
  205 
  206     def delete_analysis(self, index, reset=False):
  207         """Delete the analysis tab and data store corresponding to the index.
  208 
  209         The order of these operations is very important due to the notification of observer objects and the updates, synchronisations, etc. that follow.  If the program debugging mode is on, then printouts at each stage will occur to allow the following of the code and observer object notifications.
  210 
  211 
  212         @param index:   The index of the analysis to delete.
  213         @type index:    int
  214         """
  215 
  216         # Debugging set up.
  217         if status.debug:
  218             fn_name = sys._getframe().f_code.co_name
  219             mod_name = inspect.getmodule(inspect.stack()[1][0]).__name__
  220             class_name = self.__class__.__name__
  221             full_name = "%s.%s.%s" % (mod_name, class_name, fn_name)
  222             print("\n\n")
  223             print("debug> %s:  Deleting the analysis at index %s." % (full_name, index))
  224 
  225         # Decrement the number of analyses.
  226         self._num_analyses -= 1
  227 
  228         # Shift the current page back one if necessary.
  229         if self._current != None and self._current > index:
  230             self._current -= 1
  231             if status.debug:
  232                 print("debug> %s:  Switching the current analysis to index %s." % (full_name, self._current))
  233 
  234         # Execute the analysis delete method, if it exists.
  235         if hasattr(self._analyses[index], 'delete'):
  236             if status.debug:
  237                 print("debug> %s:  Executing the analysis specific delete() method." % full_name)
  238             self._analyses[index].delete()
  239         wx.Yield()
  240 
  241         # Delete the tab.
  242         if status.debug:
  243             print("debug> %s:  Deleting the notebook page." % full_name)
  244         self.notebook.DeletePage(index)
  245 
  246         # Delete the tab object.
  247         if status.debug:
  248             print("debug> %s:  Deleting the analysis GUI object." % full_name)
  249         self._analyses.pop(index)
  250 
  251         # Data store clean up.
  252         if not reset:
  253             # Store the pipe bundle.
  254             pipe_bundle = ds.relax_gui.analyses[index].pipe_bundle
  255 
  256             # Delete the data store object.
  257             if status.debug:
  258                 print("debug> %s:  Deleting the data store object." % full_name)
  259             ds.relax_gui.analyses.pop(index)
  260 
  261             # Delete all data pipes associated with the analysis.
  262             for pipe in pipes.pipe_names():
  263                 if pipes.get_bundle(pipe) == pipe_bundle:
  264                     if status.debug:
  265                         print("debug> %s:  Deleting the data pipe '%s' from the '%s' bundle." % (full_name, pipe, pipe_bundle))
  266                     pipes.delete(pipe)
  267 
  268         # No more analyses, so in the initial state.
  269         if self._num_analyses == 0:
  270             if status.debug:
  271                 print("debug> %s:  Setting the initial state." % full_name)
  272             self.set_init_state()
  273 
  274         # The current page has been deleted, so handle page switching to another page.
  275         elif index == self._current:
  276             # Default to the current page index - so that the switch is to the next page.
  277             page_index = self._current
  278 
  279             # Switch back one page.
  280             if self._num_analyses <= self._current:
  281                 page_index = self._current - 1
  282 
  283             # Make the switch.
  284             if status.debug:
  285                 print("debug> %s:  Switching to page %s." % (full_name, page_index))
  286             self.switch_page(page_index)
  287 
  288         # Notify the observers of the change.
  289         status.observers.gui_analysis.notify()
  290 
  291 
  292     def get_page_from_name(self, name):
  293         """Return the page corresponding to the given name.
  294 
  295         @return:    The page which matches the given name, or nothing otherwise.
  296         @rtype:     wx.Frame object or None
  297         """
  298 
  299         # Determine the analysis index.
  300         found = False
  301         for index in range(self._num_analyses):
  302             # Match.
  303             if name == ds.relax_gui.analyses[index].analysis_name:
  304                 found = True
  305                 break
  306 
  307         # No analysis found, so return nothing.
  308         if not found:
  309             return
  310 
  311         # Return the analysis page.
  312         return self._analyses[index]
  313 
  314 
  315     def load_from_store(self):
  316         """Recreate the analyses from the relax data store."""
  317 
  318         # No relax_gui data store structure, so do nothing.
  319         if not hasattr(ds, 'relax_gui'):
  320             return
  321 
  322         # A remapping table.
  323         map = {
  324             'NOE': 'noe',
  325             'R1': 'r1',
  326             'R2': 'r2',
  327             'model-free': 'mf',
  328             'Relax-disp': 'relax_disp'
  329         }
  330 
  331         # Loop over each analysis.
  332         for i in range(len(ds.relax_gui.analyses)):
  333             # The analysis name.
  334             if hasattr(ds.relax_gui.analyses[i], 'analysis_name'):
  335                 analysis_name = ds.relax_gui.analyses[i].analysis_name
  336             elif ds.relax_gui.analyses[i].analysis_type == 'NOE':
  337                 analysis_name = 'Steady-state NOE'
  338             elif ds.relax_gui.analyses[i].analysis_type == 'R1':
  339                 analysis_name = 'R1 relaxation'
  340             elif ds.relax_gui.analyses[i].analysis_type == 'R2':
  341                 analysis_name = 'R2 relaxation'
  342             elif ds.relax_gui.analyses[i].analysis_type == 'model-free':
  343                 analysis_name = 'Model-free'
  344             elif ds.relax_gui.analyses[i].analysis_type == 'Relax-disp':
  345                 analysis_name = 'Relaxation dispersion'
  346 
  347             # Compatibility with old save files.
  348             if not hasattr(ds.relax_gui.analyses[i], 'pipe_bundle'):
  349                 # First alias the pipe name as the bundle name.
  350                 ds.relax_gui.analyses[i].pipe_bundle = ds.relax_gui.analyses[i].pipe_name
  351 
  352                 # Then bundle the associated pipe into a bundle with the same name.
  353                 self.gui.interpreter.apply('pipe.bundle', pipe=ds.relax_gui.analyses[i].pipe_name, bundle=ds.relax_gui.analyses[i].pipe_name)
  354 
  355             # Set up the analysis.
  356             self._switch_flag = False
  357             self.new_analysis(map[ds.relax_gui.analyses[i].analysis_type], analysis_name, index=i)
  358 
  359         # Switch to the page of the current data pipe.
  360         self.pipe_switch()
  361 
  362         # Reset the switching flag.
  363         self._switch_flag = True
  364 
  365         # Notify the observers of the change.
  366         status.observers.gui_analysis.notify()
  367 
  368 
  369     def menu_close(self, event):
  370         """Close the currently opened analysis.
  371 
  372         @param event:   The wx event.
  373         @type event:    wx event
  374         """
  375 
  376         # Notebook not created yet, so skip.
  377         if not hasattr(self, 'notebook'):
  378             return
  379 
  380         # Execution lock.
  381         if status.exec_lock.locked():
  382             return
  383 
  384         # Get the current analysis index.
  385         index = self.notebook.GetSelection()
  386 
  387         # Ask if this should be done.
  388         msg = "Are you sure you would like to close the current %s analysis tab?" % ds.relax_gui.analyses[index].analysis_type
  389         if status.show_gui and Question(msg, title="Close current analysis", size=(350, 140), default=False).ShowModal() == wx.ID_NO:
  390             return
  391 
  392         # Delete.
  393         self.delete_analysis(index)
  394 
  395 
  396     def menu_close_all(self, event):
  397         """Close all analyses.
  398 
  399         @param event:   The wx event.
  400         @type event:    wx event
  401         """
  402 
  403         # Notebook not created yet, so skip.
  404         if not hasattr(self, 'notebook'):
  405             return
  406 
  407         # Execution lock.
  408         if status.exec_lock.locked():
  409             return
  410 
  411         # Ask if this should be done.
  412         msg = "Are you sure you would like to close all analyses?  All data will be erased and the relax data store reset."
  413         if status.show_gui and Question(msg, title="Close all analyses", size=(350, 150), default=False).ShowModal() == wx.ID_NO:
  414             return
  415 
  416         # Delete.
  417         self.delete_all()
  418 
  419         # Reset relax.
  420         reset()
  421 
  422 
  423     def menu_new(self, event, destroy=True):
  424         """Launch a wizard to select the new analysis.
  425 
  426         @param event:       The wx event.
  427         @type event:        wx event
  428         @keyword destroy:   A flag which if True will cause the analysis wizard to be destroyed.  This is used for the test suite.
  429         @type destroy:      bool
  430         """
  431 
  432         # Execution lock.
  433         if status.exec_lock.locked():
  434             return
  435 
  436         # Initialise the analysis wizard, and obtain the user specified data.
  437         self.new_wizard = Analysis_wizard()
  438         data = self.new_wizard.run()
  439 
  440         # Delete the wizard GUI element.
  441         if destroy:
  442             wx.Yield()
  443             self.new_wizard.Destroy()
  444 
  445         # Failure, so do nothing.
  446         if data == None:
  447             return
  448 
  449         # Unpack the data.
  450         analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec = data
  451 
  452         # Initialise the new analysis.
  453         self.new_analysis(analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec)
  454 
  455 
  456     def new_analysis(self, analysis_type=None, analysis_name=None, pipe_name=None, pipe_bundle=None, uf_exec=[], index=None):
  457         """Initialise a new analysis.
  458 
  459         @keyword analysis_type: The type of analysis to initialise.  This can be one of 'noe', 'r1', 'r2', 'mf' or 'relax_disp'.
  460         @type analysis_type:    str
  461         @keyword analysis_name: The name of the analysis to initialise.
  462         @type analysis_name:    str
  463         @keyword pipe_name:     The name of the original data pipe to create for the analysis.
  464         @type pipe_name:        str
  465         @keyword pipe_bundle:   The name of the data pipe bundle to associate with this analysis.
  466         @type pipe_bundle:      str
  467         @keyword uf_exec:       The list of user function on_execute methods returned from the new analysis wizard.
  468         @type uf_exec:          list of methods
  469         @keyword index:         The index of the analysis in the relax data store (set to None if no data currently exists).
  470         @type index:            None or int
  471         """
  472 
  473         # Check the C modules.
  474         if analysis_type in ['r1', 'r2'] and not dep_check.C_module_exp_fn:
  475             error_message("Relaxation curve fitting is not available.  Try compiling the C modules on your platform.")
  476             return
  477 
  478         # Check the C modules.
  479         if analysis_type == 'relax_disp' and not dep_check.C_module_exp_fn:
  480             error_message("Relaxation curve fitting will not available for this dispersion analysis.  Try compiling the C modules on your platform if you have measured full exponential curves.")
  481 
  482         # Freeze the GUI.
  483         wx.Yield()
  484         wx.BeginBusyCursor()
  485         self.gui.Freeze()
  486 
  487         # Starting from the initial state.
  488         if self.init_state:
  489             # A new sizer for the notebook (to replace the current sizer).
  490             sizer = wx.BoxSizer(wx.VERTICAL)
  491 
  492             # Create a notebook and add it to the sizer.
  493             self.notebook = wx.Notebook(self.gui, -1, style=wx.NB_TOP)
  494             sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 0)
  495 
  496             # Bind changing events.
  497             self.gui.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.on_page_changing)
  498             self.gui.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.on_page_changed)
  499 
  500             # Delete the previous sizer.
  501             old_sizer = self.gui.GetSizer()
  502             old_sizer.Clear(True)
  503 
  504             # Add the new sizer to the main window.
  505             self.gui.SetSizer(sizer)
  506             sizer.Layout()
  507 
  508         # The analysis classes.
  509         classes = {
  510             'noe': Auto_noe,
  511             'r1':  Auto_r1,
  512             'r2':  Auto_r2,
  513             'mf':  Auto_model_free,
  514             'relax_disp':  Auto_relax_disp
  515         }
  516 
  517         # Bad analysis type.
  518         if analysis_type not in classes:
  519             raise RelaxError("The analysis '%s' is unknown." % analysis_type)
  520 
  521         # Initialise the class.
  522         analysis = classes[analysis_type](parent=self.notebook, id=-1, gui=self.gui, analysis_name=analysis_name, pipe_name=pipe_name, pipe_bundle=pipe_bundle, uf_exec=uf_exec, data_index=index)
  523 
  524         # Failure.
  525         if not analysis.init_flag:
  526             # Reset.
  527             if self.init_state:
  528                 self.set_init_state()
  529 
  530             # Stop operation.
  531             return
  532 
  533         # Append the class object to the analysis window object.
  534         self._analyses.append(analysis)
  535 
  536         # Add to the notebook.
  537         self.notebook.AddPage(self._analyses[-1], analysis_name)
  538 
  539         # Increment the number of analyses.
  540         self._num_analyses += 1
  541 
  542         # Switch to the new page.
  543         if self._switch_flag:
  544             self.switch_page(self._num_analyses-1)
  545 
  546         # Set the initialisation flag.
  547         self.init_state = False
  548 
  549         # Reset the main window layout.
  550         self.gui.Layout()
  551 
  552         # Thaw the GUI.
  553         self.gui.Thaw()
  554         if wx.IsBusy():
  555             wx.EndBusyCursor()
  556 
  557         # Notify the observers of the change.
  558         status.observers.gui_analysis.notify()
  559 
  560 
  561     def on_page_changing(self, event):
  562         """Block page changing if needed.
  563 
  564         @param event:   The wx event.
  565         @type event:    wx event
  566         """
  567 
  568         # Execution lock.
  569         if status.exec_lock.locked():
  570             # Show an error message.
  571             error_message("Cannot change analyses, relax is currently executing.", "relax execution lock")
  572 
  573             # Veto the event.
  574             event.Veto()
  575 
  576 
  577     def on_page_changed(self, event):
  578         """Handle page changes.
  579 
  580         @param event:   The wx event.
  581         @type event:    wx event
  582         """
  583 
  584         # The index.
  585         self._current = event.GetSelection()
  586 
  587         # Handel calls to the reset user function!
  588         if ds.is_empty():
  589             return
  590 
  591         # Switch to the major data pipe of that page if not the current one.
  592         if self._switch_flag and pipes.cdp_name() != ds.relax_gui.analyses[self._current].pipe_name:
  593             self.gui.interpreter.apply('pipe.switch', ds.relax_gui.analyses[self._current].pipe_name)
  594 
  595         # Normal operation.
  596         event.Skip()
  597 
  598         # Notify the observers of the change.
  599         status.observers.gui_analysis.notify()
  600 
  601 
  602     def page_index_from_bundle(self, bundle):
  603         """Find the analysis associated with the data pipe bundle and return its page index.
  604 
  605         @param bundle:  The data pipe bundle to find the page of.
  606         @type bundle:   str
  607         @return:        The page index.
  608         @rtype:         int or None
  609         """
  610 
  611         # Find the index.
  612         index = None
  613         for i in range(self._num_analyses):
  614             # Matching page.
  615             if ds.relax_gui.analyses[i].pipe_bundle == bundle:
  616                 index = i
  617                 break
  618 
  619         # Return the index.
  620         return index
  621 
  622 
  623     def page_name_from_bundle(self, bundle):
  624         """Find the analysis associated with the bundle and return its name.
  625 
  626         @param bundle:  The data pipe bundle to find the page of.
  627         @type bundle:   str
  628         @return:        The page name.
  629         @rtype:         str or None
  630         """
  631 
  632         # Find the index.
  633         index = self.page_index_from_bundle(bundle)
  634 
  635         # No matching page.
  636         if index == None:
  637             return
  638 
  639         # Return the page name.
  640         return ds.relax_gui.analyses[index].analysis_name
  641 
  642 
  643     def pipe_deletion(self):
  644         """Remove analysis tabs for which the associated data pipe has been deleted."""
  645 
  646         # Loop over the analyses, noting which no longer have an associated data pipe bundle.
  647         del_list = []
  648         for i in range(self._num_analyses):
  649             if not pipes.has_bundle(ds.relax_gui.analyses[i].pipe_bundle):
  650                 del_list.append(i)
  651 
  652         # Reverse the order of the list so the removal works correctly.
  653         del_list.reverse()
  654 
  655         # Delete the analyses.
  656         for index in del_list:
  657             self.delete_analysis(index)
  658 
  659 
  660     def pipe_switch(self, pipe=None):
  661         """Switch the page to the given or current data pipe.
  662 
  663         @keyword pipe:  The pipe associated with the page to switch to.  If not supplied, the current data pipe will be used.
  664         @type pipe:     str or None
  665         """
  666 
  667         # The data pipe.
  668         if pipe == None:
  669             pipe = pipes.cdp_name()
  670 
  671         # No pipes to switch to.
  672         if pipe == None:
  673             return
  674 
  675         # Find the page.
  676         index = self.page_index_from_bundle(pipes.get_bundle(pipe))
  677 
  678         # No matching page.
  679         if index == None:
  680             return
  681 
  682         # The page is already active, so do nothing.
  683         if self._current == index:
  684             return
  685 
  686         # Switch to the page.
  687         self.switch_page(index)
  688 
  689         # Notify the observers of the change.
  690         status.observers.gui_analysis.notify()
  691 
  692 
  693     def post_reset(self):
  694         """Post relax data store reset event handler."""
  695 
  696         # Defer to the delete_all() method.
  697         self.delete_all(reset=True)
  698 
  699 
  700     def set_init_state(self):
  701         """Revert to the initial state."""
  702 
  703         # Reset the flag.
  704         self.init_state = True
  705         self._current = None
  706 
  707         # Delete the previous sizer.
  708         old_sizer = self.gui.GetSizer()
  709         old_sizer.Clear(True)
  710 
  711         # Delete the notebook.
  712         if hasattr(self, 'notebook'):
  713             del self.notebook
  714 
  715         # Recreate the GUI data store object (needed if the reset user function is called).
  716         if not hasattr(ds, 'relax_gui'):
  717             ds.relax_gui = Gui()
  718 
  719         # Recreate the start screen.
  720         self.gui.add_start_screen()
  721 
  722 
  723     def switch_page(self, index):
  724         """Switch to the given page.
  725 
  726         @param index:   The index of the page to switch to.
  727         @type index:    int
  728         """
  729 
  730         # Set the current page number.
  731         self._current = index
  732 
  733         # Switch to the major data pipe of the page if not the current one.
  734         if pipes.cdp_name() != ds.relax_gui.analyses[self._current].pipe_name:
  735             self.gui.interpreter.apply('pipe.switch', ds.relax_gui.analyses[self._current].pipe_name)
  736 
  737         # Switch to the page.
  738         wx.CallAfter(self.notebook.SetSelection, self._current)
  739 
  740         # Notify the observers of the change.
  741         wx.CallAfter(status.observers.gui_analysis.notify)