text: __name__ = "ammolite"
  __author__ = "Patrick Kunzmann"
  __all__ = ["get_and_set_pymol_instance",
             "launch_pymol", "launch_interactive_pymol", "reset",
             "setup_parameters", "DuplicatePyMOLException"]
  
  
  _pymol = None
  
  
  def get_and_set_pymol_instance(pymol_instance=None):
      """
      Get the global *PyMOL* instance.
  
      This function is intended for internal purposes and should only be 
      used for advanced usages.
  
      Parameters
      ----------
      pymol_instance : module or SingletonPyMOL, optional
          If a *PyMOL* instance is given here, the global instance is set
          to this instance.
          If *PyMOL* is already running and both instances are not the
          same, an exception is raised.
          By default *PyMOL* is started in library mode, if no *PyMOL*
          instance is currently running.
      
      Returns
      -------
      pymol_instance : module or SingletonPyMOL
          The global *PyMOL* instance.
      """
      global _pymol
      if pymol_instance is None:
          if not is_launched():
              _pymol = launch_pymol()
          return _pymol
      elif _pymol is None:
          if not hasattr(pymol_instance, "cmd"):
              raise TypeError("Given object is not a PyMOL instance")
          _pymol = pymol_instance
      elif _pymol is not pymol_instance:
          # Both the global pymol instance and the given instance are not
          # the same -> duplicate PyMOL instances
          raise DuplicatePyMOLException(
              "A PyMOL instance is already running"
          )
      return _pymol
  
  
  def is_launched():
      """
      Check whether a *PyMOL* session is already running.
  
      Returns
      -------
      running : bool
          True, if a *PyMOL* instance is already running, false otherwise.
      """
      return _pymol is not None
  
  
  def launch_pymol():
      """
      Launch *PyMOL* in object-oriented library mode.
  
      This is the recommended way to launch *PyMOL* if no GUI is
      required.
      This function simply creates a :class:`SingletonPyMOL` object,
      calls its :func:`start()` method and sets up necessary parameters using
      :func:`setup_parameters()`.
  
      Parameters
      ----------
      *args : str
          The command line options given to *PyMOL*.
      
      Returns
      -------
      pymol : SingletonPyMOL
          The started *PyMOL* instance.
          *PyMOL* commands can be invoked by using its :attr:`cmd`
          attribute.
      """
      from pymol2 import SingletonPyMOL
      global _pymol
  
      if is_launched():
          raise DuplicatePyMOLException(
              "A PyMOL instance is already running"
          )
      else:
          _pymol = SingletonPyMOL()
          _pymol.start()
          setup_parameters(_pymol)
      return _pymol
  
  
  def launch_interactive_pymol(*args):
      """
      Launch a *PyMOL* GUI with the given command line arguments.
  
      It starts *PyMOL* by calling :func:`pymol.finish_launching()`,
      reinitializes *PyMOL* to clear the workspace and sets up necessary
      parameters using :func:`setup_parameters()`.
  
      Parameters
      ----------
      *args : str
          The command line options given to *PyMOL*.
      
      Returns
      -------
      pymol : module
          The :mod:`pymol` module.
          *PyMOL* commands can be invoked by using its :attr:`cmd`
          attribute.
      """
      import pymol
      global _pymol
  
      if is_launched():
          if _pymol is not pymol:
              raise DuplicatePyMOLException(
                  "PyMOL is already running in library mode"
              )
          else:
              raise DuplicatePyMOLException(
                  "A PyMOL instance is already running"
              )
      else:
          pymol.finish_launching(["pymol"] + list(args))
          _pymol = pymol
          pymol.cmd.reinitialize()
          setup_parameters(_pymol)
      return pymol
  
  
  def reset():
      """
      Delete all objects in the PyMOL workspace and reset parameters to
      defaults.
  
      If *PyMOL* is not yet running, launch *PyMOL* in object-oriented
      library mode.
      """
      global _pymol
  
      if not is_launched(): 
          _pymol = launch_pymol()
      _pymol.cmd.reinitialize()
      setup_parameters(_pymol)
  
  
  def setup_parameters(pymol_instance):
      """
      Sets *PyMOL* parameters that are necessary for *ammolite* to interact
      properly with *PyMOL*.
  
      pymol_instance : module or SingletonPyMOL or PyMOL, optional
          If *PyMOL* is used in library mode, the :class:`PyMOL`
          or :class:`SingletonPyMOL` object is given here.
          If otherwise *PyMOL* is used in GUI mode, the :mod:`pymol`
          module is given.
      """
      # The selections only work properly,
      # if the order stays the same after adding a model to PyMOL
      pymol_instance.cmd.set("retain_order", 1)
  
  
  class DuplicatePyMOLException(Exception):
      pass