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 16, 2007 - 17:09:
On Wed, 2007-01-17 at 01:53 +1100, Edward d'Auvergne wrote:
On 1/16/07, Chris MacRaild <c.a.macraild@xxxxxxxxxxx> wrote:
On Mon, 2007-01-15 at 17:44 +1100, Edward d'Auvergne wrote:

[snip]

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

You still need a list (array) or dictionary (hash) type structure to
store multiple run objects.  'self.relax.data' would be a dictionary
type object with key-value pairs, the key being the run name and the
value being a standard class instance object containing all the data
associated with the run as objects.  The dictionary would be more
logical than an array in this case.


The issue here is whether the user and/or developer should be dealing
with a run name (a string) or the run object itself. Currently the user
creates a new run with:

run.create(run_name, run_type)

and then uses the string, run_name, to address the object. In this
idiom, a dictionary of runs is clearly an appropriate structure.

Alternatively, we could have the user create a run with:

my_run = run.create(run_type)

Then the user has the run as an object, which they can make current or
pass to relax commands as required. In this idiom, a dictionary of runs
is an unnecessary abstraction.

You have mentioned the run object idea before, although I can't find
your post on the subject.


Currently, the relax interface is entirely script orientated, not object
orientated, so the alternative above is a fairly fundamental change in
interface design.

I don't favour an object orientated user interface, because oo tends to
be fairly intimdating to non-programmers. On the other hand, the relax
code-base could benefit from being more object orientated. So I propose
the following arrangement:

I have thought of your idea quite a bit, but am of the same opinion as
that stated in your above paragraph.  The idea of having the run
objects as things that the user has at their fingertips to manipulate,
pass to functions, etc is quite powerful.  However it does add
significant complexity to the prompt/script UI.  I can clearly see the
idea embedded in a GUI design though whereby the data pipe (previously
called a run) is represented as a physical object (either in 2D or 3D)
which can be manipulated and the user functions applied to.


all runs are stored in a dictionary, keyed by run name, but only the
run-selection machinery should access this dictionary. The current run
should be the object self.relax.data.run (or something simiar), and all
relax functions should operate on that object.

I agree, however I would extend this using the global variable ideas
Gary proposed 
(https://mail.gna.org/public/relax-devel/2007-01/msg00013.html,
Message-id: <f001463a0701071314i61276e67hde685fe3afb8fe42@xxxxxxxxxxxxxx>).
 So instead of using 'self.relax.data.run' the data container of the
current run, which is located in the dictionary type object
'self.relax.data[]', could be aliased as say 'data_pipe' or
'current_pipe' and placed into '__builtin__'.  Then any part of relax
can access the data of the current data pipe by referring directly to
'current_pipe'.  Maybe a better variable name would be 'cdp' (current
data pipe)?  Or maybe simply 'data'?

In addition, I don't believe the name 'run' encapsulates the concept
at all.  This name is a relic which is not at all related to its
current use (https://mail.gna.org/public/relax-devel/2006-10/msg00056.html,
Message-id: 
<1160555137.9523.70.camel@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>).
 The current use of the name 'run' encapsulates the segregation of the
data.  This is why I prefer the words 'data pipe' or 'pipe' over
'run'.



I wasn't trying to express an opinion over where or how the current run
object is stored or aliased or even over what it is called. I simply
wanted to say that within the relax code, we should address the run as
an object, not as a string that serves as key to the dictionary of runs.
(I had to adopt a position on names, locations, etc only in a vain
attempt to avoid my arguments becoming intractably abstract)

ie. current_pipe should be the current pipe, not the name of the current
pipe, whether current_pipe is an attribute of __builtin__ or of
self.relax.data or of any other class we care to nominate.

On the other hand, I think we agree that the user command pipe.current()
should return the name of the current pipe, and similarly all user
commands should address runs with run names.


If I were to express an opinion on the question of the appropriate name
for the 'run' idea, I would have to say that pipe is better than run,
but still not ideal. Essentially because the idea of a run/pipe in relax
is actually quite different to the pipe idea exemplified by nmrPipe, eg.
The better metaphor might be of the production line, but
current_production_line will quickly become unwieldy!!




Thus we would have user functions:

run.create(run_name, run_type):
    self.relax._runs[run_name] = new_run(run_type)

The 'new_run' would be an empty data container (a class instance) and
the data pipe type would be a simple string variable inside this
container.  Hence:

pipe.create(pipe_name, pipe_type):
    self.relax.data[pipe_name] = PipeContainer(pipe_type)


run.make_current(run_name):
    self.relax.data.run = self.relax._runs[run_name]

I see the word 'switch' is a little more direct than 'make_current',
although there may be even better alternatives.  What do you think
Chris?

Sure, that works.


pipe.switch(pipe_name):
    __builtin__.current_pipe = self.relax.data[pipe_name]


run.current():
    return self.relax.data.run.name

pipe.current():
    return current_pipe.name

Having the name stored in the dictionary as a key and in the data pipe
container as the 'name' variable is a little redundant.  Maybe the
current pipe name should be stored as say 'self.relax.current_pipe'?

I like the clarity of having an attribute for name. In fact in other
contexts I have coded a sub-class of dictionary which automates this
process so there can never be a conflict between the key and the 'name'.
Something like:

class NamedDict(dict):
    def __setitem__(self, key, val):
        dict.__setitem__(self, key, val)
        self[key].name = key
        


run.run_names():
    return self.relax._runs.keys()

pipe.display():
    print "%20s%20s" % ('Data pipe name', 'Data pipe type')
    for key in self.relax.data:
        print "%20s%20s" % (key, self.relax.data[key].pipe_type)


run.delete(run_name):
    if run.current() == run_name:
        self.relax.data.run = None
    del self.relax._runs[run_name]

pipe.delete(pipe_name):
    if self.relax.current_pipe == pipe_name:
        __builtin__.data = None
    del self.relax.data[pipe_name]


run.delete_all():
    self.relax.data.run = None
    self.relax._runs = {}

pipe.delete_all():
    __builtin__.current_pipe = None
    self.relax.data = PipeDictionary()

The point of 'PipeDictionary()' rather than {} is because many of the
objects in 'self.relax.data' are special.  They have their
'__repr__()' methods modified so that when you type the object name at
the prompt, you get a formatted printout rather than something like:

<__main__.Data instance at 0xb764732c>


This way the abstraction of the dictionary of runs is cleanly hidden
from the developer who chooses to work with objects, but the scripting
style of the user interface is maintained.

Don't forget that the dictionary type 'self.relax.data' is an object,
as are the values corresponding to its keys - the data pipe
containers.  In Python, essentially everything is an object.

Of course. The point is not whether or not run names are objects, the
point is that they are not the objects we are really interested in.
Again, I just chose to use a certain set of terms to try and make my
point clear.


Edward





Related Messages


Powered by MHonArc, Updated Fri Jan 19 08:20:25 2007