Skip to main content


Showing posts from September, 2010

Muhahahaha! Things can always be more complex...

A good measure of how right a model or an implementation is can be how quickly it extends to more complex situations:
This is essentially the same except that 'SSE' has been added (no big deal) but also the leaf list has been generalised to AbstractLeafCollection. :)
I'm sure there are better ways to do this, but it fits neatly with some existing ideas I had on searching through lists vs searching through sets.

Rose Forests

Carl Masak blogged about tree data structures, which caught my interest because of a pet-project of mine (tailor; a structure description and measurement tool) where I found myself using trees a lot. An awful lot. Perhaps ... too much.
Anyway, a related tweet by AudreyT mentioned an article called "Origami Programming" by Jeremy Gibbons. Which is in haskell (perhaps not surprisingly), a language I don't speak very well. However, while reading - and not understanding it - I did get one thing which was the idea of having a tree datatype where the node (called a 'rose') references a forest (a list of roses). I think that's right.
In any case, it solves a object-modelling problem for me that I had. The difficulty was that protein structures are hierarchical, yes, but have a strange mixed hierarchy of types. Perhaps this is obvious to haskell programmers and compiler-code writers, but this makes it very difficult to use the 'simple' tree datatype, where a No…

Molecule Layouts

I've been doing experimental work on layouts for the CDK. Not for atoms, exactly, for which the StructureDiagramGenerator is doing a pretty good job - could be better, of course, but what couldn't?
No, layout of MoleculeSets, and Reactions. Well actually IMoleculeSets and IReactions. With an ILayout class - my apologies to anyone who doesn't like generics, but it can be quite useful. Anyway, here is an example of what it is looking like at the moment:
Hmmm. Well, it is a grid I suppose. The problems with the ring bonds are known to me, please do not mention them >:|
The code for this is quite short: IMoleculeSet moleculeSet = makeMolSet();
ILayout<IMoleculeSet> gridLayout = new GridMoleculeSetLayout(3, 3);
makeImage(moleculeSet, gridLayout, "three_by_three", 500, 500);
where the methods 'makeMolSet' and 'makeImage' do what you might expect (I hope :). Similarly:IMoleculeSet molSet = makeMolSet();
AxisOrientation o = AxisOrientation.PLUS_X_PLUS_Y;

Consistent Zoom with Models of Different Scales

So there is a way to get the zoom to work:
(to zoom on the picture, click for bigger :)
The approach taken here is to create graphical objects (LineElement, RectangleElement, etc) that are scaled at the origin, but not zoomed or translated to the center of the draw area. These last two parts of the transform are then added to the graphics transform.
One downside of altering the transform in the graphics is that if we want to draw extra stuff on the panel (like the detail string "Zoom = x, Scale = y" in the picture above) the original transform has to be captured before drawing, then restored after.
For example, see this commit:

Scaling and Text

An obvious question about the CDK rendering code is : "Why not scale text with AffineTransform?" So, of course this is possible, and works quite nicely - but there is a cost.
One of the goals of the rendering code is to start from models of any scale, and render them as consistently sized diagrams on screen. By 'scale' here I simply mean the average distance between points. So the CDK layout code might use a distance of (say) 1 between two carbon atoms, but a file with a structure made in some other chemical editor might have an average atom-atom distance of 100. These are unitless values, by the way.
Now, what we could have done was transform the coordinates in the model to a consistent scale, then rendered these transformed coordinates. What we chose to do, however, was to calculate a single transform for the model and draw with this. If you use this transform to scale the graphics object before drawing you get this for a model scale of 10:

and this for a model scale…

Generic Rendering

Egon++ is continuing the process of merging the CDK-JCP rendering core into CDK master. Some proposed generification of the classes was made on the mailing list, and here is a sketch of some of the classes and interfaces:
I realise that this looks horribly complex, but the question is : "Is it just complex enough, or too complex?". One of the things missing from the diagram is layout - there may be a need for classes like LinearMoleculeSetLayout or GridMoleculeSetLayout. Oh, and yes (you guessed it!) an IMoleculeSetLayout and ChemObjectLayout classes :)
The goal here is not to make convoluted code, but to avoid repeating stuff. A reaction renderer should know how to layout and paint molecule sets, and then pass on the task to the molecule set renderer, and so on. Some key things to avoid will be a) not to relayout on each paint and b) generate the diagrams in the right places, at the correct scales. I think that this will be possible.

How (not) to remove items from a (CDK) list

So there I was, trying to remove all mappings from a Reaction like this:
for (int i = 0; i < reaction.getMappingCount(); i++) { reaction.removeMapping(i); }and found that only half the mappings were being removed ... can you see why? :)
In fact, this is not some obscure CDK bug, but a logic error on my part. Equivalent code is this: List list = getListSomehow();
for (int i = 0; i < list.size(); i++) { list.remove(i) }using for example a java.util.ArrayList. The problem is that the index (i) is being tested against a changing number (the size). Once half the items have been removed, i is at the half-way point, so on the next pass it stops.
One way to 'solve' this is to go backwards: for (int i = list.size(); i > 0; i--) { reaction.removeMapping(i); }but this is slightly less clear than just :
List list = getListSomehow();
int size = list.size();
for (int i = 0; i < size; i++) { list.remove(i) }which is clearer. Of course, even better is the List method removeAll(). It would …