Molecule Changed Signal

Hi,

As I have been working on the ribbon code and looking forward to adding
support for surfaces it becomes more apparent we need a signal for when the
molecule is changed. I remember Donald mentioning something about it months
ago but as far as I am aware this does not currently exist.

In order to get reasonable performance for things like ribbons and surfaces
the calculations should be done once for the molecule as it is loaded and
then cached. If the molecule is changed a signal would be emitted and the
engines/tools that need it could receive the signal and recalculate if they
are active.

This would mean any tool or extension that changes any atom or bond would need
to emit this signal. Does this seem like a reasonable approach? Are there any
alternative methodologies I should consider?

Opinions welcome.

Thanks,

Marcus

There is already a signal for this. Actually there are two. For all
primitives there is a signal when a primitive gets added
Molecule::primitiveAdded(Primitive *), a signal when a primitive gets
deleted Molecule::primitiveRemoved(Primitive *), and when you modify a
molecule you are supposed to call Molecule::update() which emits a
signal Molecule::updated() and also emits a signal
::primitiveUpdated(Primitive ) with the parameter equal to the molecule
that had ::update() called on it. As a side: when you update only one
atom you are to call Atom::update() and that emits
Molecule::primitiveUpdated(<atom that got called ::update() on>). This
means we can tell things “hey, only this single atom got updated”. The
versatility of this is that we can connect a single slot to the three
Molecule::primitive
functions and conveniently…
Molecule::primitiveUpdate(Primitive *) is also emitted when the molecule
itself is updated, with the parameter of the molecule itself.
Alternatively you can connect to Molecule::updated() but this is not as
dynamic as you don’t get a pointer to the primitive itself.

However, there are a few things i’m curious about. Remember that
engines keep an internal list of the primitives they are to render. So
does the ribbon engine ALWAYS have to work on a molecule or does it work
on individual atoms or residues? Also there is a virtual function
Engine::updatePrimitive() that gets called when a primitive is updated
in the main code. So your engine only needs to reimplement this
function and booyah, you now can cache your stuff. But you would also
probably want to reimplement Engine::addPrimitive and
Engine::removePrimitive also.

Tools are a little different from engines. We need to be careful here
design wise. If there is stuff to improve performance for graphics then
it should go in the Engines. If this information needs to be available
for the tools for some reason (i don’t have a good example) then we need
to rethink our tools.

So far so good with following a Model-View-Controller architecture so we
should think about it that way.

Engines+GLWidget == View
Tools + Extensions == Controller
Molecule == Model

In this philosophy the view basically gives us a representation of the
model. The view should NOT directly interact with the model. To do so
the view relies on the controller(s) which use the view and input from
the user to modify the model. Now we could, with very little change,
make it so that Tools have a Tool::initialize(Molecule *mol) and
Tool::reset() or something like that but i’m somewhat hesitant to do
that right away because this point the Tool has access to the model
because of the GLWidget.

One thing which is bad is to save information when mouseMove /
mousePressed functions get called. This is bad:

void MyTool::mousePressed(GLWidget *widget, …)
{
m_mol = widget->molecule();

}

It can work but it’s a hack for a bad API. What if the GLWidget loads
a new molecule and we don’t properly clear our ‘m_mol’ pointer. Bugs
can easily crop up and they’re a pain the ass to track down. If Tools
need access to Molecule all the time (and remember, one instance of a
tool per molecule) then we should put in the initialization functions.

I should try to write more about this on the WiKi. And comments feel
free.


Donald

(Fri, Oct 26, 2007 at 08:57:35PM -0400) “Marcus D. Hanwell” marcus@cryos.org:

Hi,

As I have been working on the ribbon code and looking forward to adding
support for surfaces it becomes more apparent we need a signal for when the
molecule is changed. I remember Donald mentioning something about it months
ago but as far as I am aware this does not currently exist.

In order to get reasonable performance for things like ribbons and surfaces
the calculations should be done once for the molecule as it is loaded and
then cached. If the molecule is changed a signal would be emitted and the
engines/tools that need it could receive the signal and recalculate if they
are active.

This would mean any tool or extension that changes any atom or bond would need
to emit this signal. Does this seem like a reasonable approach? Are there any
alternative methodologies I should consider?

Opinions welcome.

Thanks,

Marcus


This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/


Avogadro-devel mailing list
Avogadro-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/avogadro-devel

On Friday 26 October 2007 22:25:22 Donald Ephraim Curtis wrote:

There is already a signal for this. Actually there are two. For all
primitives there is a signal when a primitive gets added
Molecule::primitiveAdded(Primitive *), a signal when a primitive gets
deleted Molecule::primitiveRemoved(Primitive *), and when you modify a
molecule you are supposed to call Molecule::update() which emits a
signal Molecule::updated() and also emits a signal

::primitiveUpdated(Primitive *) with the parameter equal to the molecule

that had ::update() called on it. As a side: when you update only one
atom you are to call Atom::update() and that emits
Molecule::primitiveUpdated(<atom that got called ::update() on>). This
means we can tell things “hey, only this single atom got updated”. The
versatility of this is that we can connect a single slot to the three
Molecule::primitive* functions and conveniently…
Molecule::primitiveUpdate(Primitive *) is also emitted when the molecule
itself is updated, with the parameter of the molecule itself.
Alternatively you can connect to Molecule::updated() but this is not as
dynamic as you don’t get a pointer to the primitive itself.

It sounds like there are certainly more than enough signals for me to work
with.

However, there are a few things i’m curious about. Remember that
engines keep an internal list of the primitives they are to render. So
does the ribbon engine ALWAYS have to work on a molecule or does it work
on individual atoms or residues? Also there is a virtual function
Engine::updatePrimitive() that gets called when a primitive is updated
in the main code. So your engine only needs to reimplement this
function and booyah, you now can cache your stuff. But you would also
probably want to reimplement Engine::addPrimitive and
Engine::removePrimitive also.

Right now it calls list = primitives().subList(Primitive::ResidueType); to get
all of the primitives that are of the residue type. It then scans through all
the atoms of the residue for CA atoms. Assembles all the CA atoms in the
chain and so it should work out right if atoms are removed too but I haven’t
tested that yet.

Tools are a little different from engines. We need to be careful here
design wise. If there is stuff to improve performance for graphics then
it should go in the Engines. If this information needs to be available
for the tools for some reason (i don’t have a good example) then we need
to rethink our tools.

I was thinking more of the bond centric tool but I think I was wrong on that
example.

So far so good with following a Model-View-Controller architecture so we
should think about it that way.

Engines+GLWidget == View
Tools + Extensions == Controller
Molecule == Model

That is certainly the way I saw it, but the tools do sometimes do a little
visualisation too. I think you are right that the current situation works
just fine for all examples I can think of right now at least.

In this philosophy the view basically gives us a representation of the
model. The view should NOT directly interact with the model. To do so
the view relies on the controller(s) which use the view and input from
the user to modify the model. Now we could, with very little change,
make it so that Tools have a Tool::initialize(Molecule *mol) and
Tool::reset() or something like that but i’m somewhat hesitant to do
that right away because this point the Tool has access to the model
because of the GLWidget.

One thing which is bad is to save information when mouseMove /
mousePressed functions get called. This is bad:

void MyTool::mousePressed(GLWidget *widget, …)
{
m_mol = widget->molecule();

}

It can work but it’s a hack for a bad API. What if the GLWidget loads
a new molecule and we don’t properly clear our ‘m_mol’ pointer. Bugs
can easily crop up and they’re a pain the ass to track down. If Tools
need access to Molecule all the time (and remember, one instance of a
tool per molecule) then we should put in the initialization functions.

Thanks for explaining this, I think it is good to have it on the mailing list.

I should try to write more about this on the WiKi. And comments feel
free.

I have been doing some more work on this today but have made limited progress.
Think I have figured out how to tesselate but the maths or opengl is letting
me down. I will debug more and see if I can make more progress tomorrow.
Thanks for going into more detail on the available signals. The model/view
stuff I already got but it is certainly good to have it documented.

Thanks,

Marcus

On Friday 26 October 2007 22:25:22 Donald Ephraim Curtis wrote:

There is already a signal for this. Actually there are two. For all
primitives there is a signal when a primitive gets added
Molecule::primitiveAdded(Primitive *), a signal when a primitive gets
deleted Molecule::primitiveRemoved(Primitive *), and when you modify a
molecule you are supposed to call Molecule::update() which emits a
signal Molecule::updated() and also emits a signal

As I was implementing the cached chains for the ribbon engine I noticed that
the engines seem to call addPrimitive etc for each atom as a molecule is
loaded whether that engine is active or not. So as far as I can tell as we
add more and more engines the load time for large items will get larger and
larger.

Is this correct or did I miss something? Wouldn’t it be better for inactive
engines to just return until they are first used, or for them have some
concept of “we are loading a whole molecule - copy it all at the end”? It has
been a really long day so it is always possible I have missed something too.

Thanks,

Marcus

I noticed this. You are correct.

The correct way to do this would be to reimplement
GLWidget::setMolecule().

Right now what it does is go through each primitive in a Molecule and do
engine::addPrimitive.

What it should really do is just do
Engine::setPrimitives(d->primitives); at the end of the function and
remove the loops that do ->addPrimitive.

I’ll make the updates as SOON as i get the chance. But beware you need
to also reimplement ::setPrimitives in the ribbon engine then.

(Thu, Nov 01, 2007 at 02:03:22PM -0400) “Marcus D. Hanwell” marcus@cryos.org:

On Friday 26 October 2007 22:25:22 Donald Ephraim Curtis wrote:

There is already a signal for this. Actually there are two. For all
primitives there is a signal when a primitive gets added
Molecule::primitiveAdded(Primitive *), a signal when a primitive gets
deleted Molecule::primitiveRemoved(Primitive *), and when you modify a
molecule you are supposed to call Molecule::update() which emits a
signal Molecule::updated() and also emits a signal

As I was implementing the cached chains for the ribbon engine I noticed that
the engines seem to call addPrimitive etc for each atom as a molecule is
loaded whether that engine is active or not. So as far as I can tell as we
add more and more engines the load time for large items will get larger and
larger.

Is this correct or did I miss something? Wouldn’t it be better for inactive
engines to just return until they are first used, or for them have some
concept of “we are loading a whole molecule - copy it all at the end”? It has
been a really long day so it is always possible I have missed something too.

Thanks,

Marcus


This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/


Avogadro-devel mailing list
Avogadro-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/avogadro-devel