mailre: Redesign of the relax data model: 2. A new run concept


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by Chris MacRaild on January 10, 2007 - 13:29:
On Sun, 2007-01-07 at 21:14 +0000, gary thompson wrote:

[snip]


  2.  A new run concept

  2.1  Parcelling up an abstract space

  The general idea is to further increase the prominence of the 'run'.
  Rather than relax executing in an abstract space where the 'run' is
  passed into each user function as necessary, the idea is that relax
  executes within a space dedicated to a certain 'run'.  So if at the
  relax prompt, you could type a user function such as:

  relax> run.current()
  'm8'

  By working in the 'm8' run space, each user function can be executed
  without the need for the 'run' argument.  Other user functions, such as
  'run.switch()', can be used to change between runs.

I agree that carrying the run argument throughout the data structure
is an annoying problem and I like the solution but here is an
extension to it that may enegender more felxibility

There is an interesting parallel here... basically the proposal
consists of the proposal that there should always be a current run
(much in the same way that most shells have a present working
directory). However, it is worth noting that many unix tools take a
directory argument which overrides the current working directory and
this engenders both simplicity and flexibility as to which 'context' a
command runs in.

  2.2  The run data model

  The current run name could be stored in the single data structure
  'self.relax.run'.  The relax data structure could then be accessed by
  typing 'self.relax.data[self.relax.run]'.  I.e. 'self.relax.data' is a
  DictType object (it has key-value pairs) in which the run name key is
  associated with a specific data container.  As most data structures in
  the current relax data model are associated with a run (e.g.
  'self.relax.data.diff[self.run]', 'self.relax.data.res[self.run]',
  'self.relax.data.pdb[self.run]', etc), the data model significantly
  simplifies.

now following on from the comment above I would suggest that a data
structure  containing a stack of runs be a good idea.. consider a
command that took a run parameter:

def command(run=None):
   self.relax.run.push(run)
   ... do something
   self.relax.run.pop()

now there are some intrinsic problems with this setup (basically it is
far too easy to pop and then degugging really does become a
nightmare.... However, python actually has at least three solutions to
this(not all ow which are available in version 2.4 the with solution
requires 2.5)

1. decorators (python 2.4)
   @relax_command
   def command():
      ...do something

   @relax_command then wraps command in a self.relax.run.push/pop(run) pair


2. define relax_command as a functor and then have a default
relax_command functor that wraps around with a push and a pop

   class relax_command():
      def __init__(self,function):
          self.function=function
      def __call__(self,*args):
      #find run arg and save in local variable and remove from args
      self.relax.push()
      self.function(args)
        self.relax.pop()


I'm not sure that the stack idea gains us anything over the run-loop
idea I proposed earlier
https://mail.gna.org/public/relax-devel/2006-10/msg00060.html

The idea of implimenting the run-loop as a functor is a good one though.

We'd have something like:

class Relax_command():
    def __init__(self, function):
        self.function = function
    def __call__(self, *args, **kwds):
        if 'runs' in kwds.keys():
            runs = kwds['runs']
            del kwds['runs']
            current_run = run.current()
            for run_name in runs:
                run.switch(run_name)
                self.function(*args, **kwds)
        else:
            self.function(*args, **kwds)

Then each user command is simply an instance of Relax_command


Chris




3. the with statement (python 2.5)
see 
http://www.dalkescientific.com/writings/diary/archive/2006/08/23/with_statement.html

Some asides

A.  I believe the runs that are passed around in relax are strings
which are then used to lookup data in a map. Why not just have
(runs/pipes) as objects... Then for example the call

self.relax.data[self.relax.run]

above becomes

self.relax.run.data a much more object orientated and encapsulated structure

B. There is a twist here, if relax is a global variable referenced by
everything if you want to run relax in a threaded manner
(multiprocessor machines are becoming more and more popular) then
self.relax poses a problem as we may need a different relax variable
for each processor so the relax variable needs to be acessed from
thread local storage cf
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302088)


  More information about the data model change is given in the message at
  located at https://mail.gna.org/public/relax-devel/2006-05/msg00008.html
  (Message-id:
  <7f080ed10605232038j5036278dg39136d75a05a9904@xxxxxxxxxxxxxx>) and the
  response located at
  https://mail.gna.org/public/relax-devel/2006-05/msg00010.html
  (Message-id:
  <7f080ed10605241912i7c35f574i94f139588c5fa16b@xxxxxxxxxxxxxx>).


  2.3  The pipe concept

  A single run can be thought of as a pipe where data is input, processed,
  or output as user functions are called.  There are different types of
  pipe for different analyses, e.g. a reduced spectral density mapping
  pipe, a model-free pipe, an exponential curve-fitting pipe, etc.  When
  running relax you choose which run (or pipe) you are currently in and
  the 'run.switch()' user function allows you to jump between multiple
  runs (or pipes).  The modification of user functions in which runs are
  combined or branched (which can be thought of as the pipes merging or
  splitting) would be straight forward.  For example the
  'model_selection()' user function currently accepts the following
  arguments:

  model_selection(self, method=None, modsel_run=None, runs=None)

  In this case the 'modsel_run' can be dropped and the results of model
  selection placed into the current run (or pipe).  The 'run' user
  function class could contain the following user functions for pipe
  manipulation:

  run.copy()    # Create a new run (or pipe) with the current contents of
  another run (or pipe).
  run.create()    # Create a new run (or pipe).  Switch to this pipe by
  default.
  run.current()    # Print the current run (or pipe).
  run.delete()    # Delete the given run (or pipe).
  run.delete_all()    # Delete all runs.  Essentially deleting
  'self.relax.data'.

you might want to consider a nullObject here so that if all runs are
deleted you don't crash just raise error messages...

  run.hybridise()    # Fuse two runs (or pipes) into the current run (or
  pipe).  Overlapping data in the two runs must be identical!
  run.list()    # Print all runs (or pipes).
  run.switch()    # Switch to another run (or pipe).

Now here is a further comment if run were an object that contained its
own data many of these processes could be dealt with using pythons own
semantics

e.g.

run.copy():

      from copy import copy

      new_run=copy(run)

run.create():
      new_run = Run()

run.delete():
      new_run = Run()
      new_run =  None # run dissapears due to grbage collection/ref counts



  One evolutionary path of the run concept which could be followed with
  this set of proposed changes is to completely replace it with the pipe
  concept.  All instances of 'run' in relax would be renamed to 'pipe'.
  For example 'run.create()' will become 'pipe.create()',
  'self.relax.data[self.relax.run]' will become
  'self.relax.data[self.relax.pipe]', etc.  I believe that the name 'pipe'
  is a better representation of the run concept than 'run'.  What do you
  think of the idea?

another name would be processor or command

  The hypothetical ideas of this paragraph are not part of the current
  proposals, however they further illustrate the pipe concept.  The pipe
  concept is highly amenable for the creation of a Qt GUI.  Program
  execution could be directed by a graphical 'pipe' construction (possibly
  in 3D using OpenGL).  Elements of the pipe, equivalent to the user
  functions of the prompt and script interfaces, could be dragged from
  toolbars and dropped into a canvas.  These could be linked together by
  moving the element with the mouse and having it click into other
  elements.  For example 'run.delete()' (alternatively 'pipe.delete()')
  could be represented as a cap added to the end of a pipe - its execution
  removes all the data of that pipe from memory.  This pictorial
  representation of execution would be very powerful and intuitive.
  Scripts could be imported into the GUI and represented as a network of
  interconnected pipes and vice versa.  Execution of relax could even be
  animated as semi-transparent pipes filling up bit by bit as each user
  executes.  Imagination is the only limit!





regards
gary

_______________________________________________
relax (http://nmr-relax.com)

This is the relax-devel mailing list
relax-devel@xxxxxxx

To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-devel





Related Messages


Powered by MHonArc, Updated Thu Jan 11 08:20:14 2007