Marvin Sketch: 2D bounding boxes for reaction components?

User 1a8d11549a

19-03-2011 07:36:29

Hi,


I just started evaluating Marvin.Net, so maybe there's a simple answer to this:  I wondered if there is a simple way to retrieve via the .NET API from an open Marvin Sketch instance the 2D bounding boxes of e.g. the components A, B, C and D of a sketch containing the reaction A + B -> C + D. By 2D bounding boxes I mean the smallest possible rectangle enclosing a component, preferably taking into account abbreviated groups (i.e. their group label string position instead of their original atom positions). - Thanks for your help!

ChemAxon bd13b5bd77

21-03-2011 08:12:10

Dear John,


sending you a sample code soon.


Viktor

User 1a8d11549a

21-03-2011 09:03:07

Very much appreciated, looking forward to it. Thanks Victor!

ChemAxon bd13b5bd77

21-03-2011 15:00:19

I just wanted to break the long silence :) with this example:


 


         chemaxon.struc.RxnMolecule _rxnMolecule = (chemaxon.struc.RxnMolecule)   chemaxon.formats.MolImporter.importMol(data);


         int reactantCount =  _rxnMolecule.getComponentCount(chemaxon.struc.RxnMolecule.REACTANTS); 
         int productCount =  _rxnMolecule.getComponentCount(chemaxon.struc.RxnMolecule.PRODUCTS); 
         int agentCount =  _rxnMolecule.getComponentCount(chemaxon.struc.RxnMolecule.AGENTS);


         int componentCount = reactantCount + productCount + agentCount;



         //calculate atom and bond coordinates
         if (componentCount > 0) {
            _rxnMolecule.clean(2, "");
         }



         for(int index = 0; index < reactantCount; index++){
            chemaxon.struc.Molecule molecule = _rxnMolecule.getComponent(chemaxon.struc.RxnMolecule.REACTANTS, index);
            var point =  molecule.getEnclosingCube();
         }


http://www.chemaxon.com/jchem/doc/dev/java/api/chemaxon/struc/MoleculeGraph.html#getEnclosingCube()


I check all the reactants and products afterwards and it seems that the co-ordinates follow each other in a valid order and look more or less okay. However I found them all too small. It seems that - numbers are relative tho the reaction center.


I will investigate a little bit more and be back to you once I have the most proper answer.

User 1a8d11549a

22-03-2011 09:35:50

Thanks for your preliminary code, Victor. I've played a bit with it (although I'm a VB.net programmer, but don't worry unless it's not tons of code). One thing I did was to replace the first code line by the the following line, in order to get the sketch of the running Marvin instance (sketchPane is an MSketchPane within the running JFrame), which seems to work nicely.


RxnMolecule _rxnMolecule = (chemaxon.struc.RxnMolecule)sketchPane.getMol();


I know that you are still working on the code, but please still allow me some questions at this stage. Concerning "molecule.getEnclosingCube()": What is the coordinate system of the resulting cube?


[Viktor] - atomic.


Are these angstroms?


[Viktor] - yes.


 Then how can this coordinate system be mapped to the pixel coordinates of the sketch?


[Viktor] - yes, use Molprinter to link the atomic coords to real life pixels.


 Also, the position of contracted groups seems a bit confusing in my perliminary tests: If I abbreviate and contract a large group in a reactant, the resulting cube coordinates become larger instead of smaller, which I can't explain.


[Viktor] - I think the contracted (abbreviated) groups/atoms have no physical extension. This can be seen both in angstroms and in pixels.


And finally: What is the purpose of "_rxnMolecule.clean(2, "");" line? Is it required for a 2D sketch, and if yes, will it modify the original positions of atoms in the sketch (which would not be desired)?


[Viktor] - you can skip it.


Again, thanks for working on this ...


 

ChemAxon bd13b5bd77

22-03-2011 11:28:13

Dear John,


I tried to refine the code, it looks much better now, yes, it does not matter how you import the molegule, directly from sketch or from a string, I stay using the string (data variable):


         chemaxon.struc.RxnMolecule rxnMolecule = (chemaxon.struc.RxnMolecule)chemaxon.formats.MolImporter.importMol(data);


         // Create a writable image
         BufferedImage im = new BufferedImage(400, 400,
                                              BufferedImage.TYPE_INT_ARGB);
         Graphics2D g = im.createGraphics();
         Rectangle rect = new Rectangle(20, 20, 360, 200);
         // Paint the molecule
         chemaxon.marvin.MolPrinter drawer = new chemaxon.marvin.MolPrinter(rxnMolecule);
         drawer.setScale(drawer.maxScale(rect)); // fit image in the rectangle
         drawer.setBackgroundColor(Color.white);
         drawer.paint(g, rect);



         int reactantCount =  rxnMolecule.getComponentCount(chemaxon.struc.RxnMolecule.REACTANTS); 


         for(int index = 0; index < reactantCount; index++){
            chemaxon.struc.Molecule molecule = rxnMolecule.getComponent(chemaxon.struc.RxnMolecule.REACTANTS, index);
            molecule.setGUIContracted(true);
            var points =  molecule.getEnclosingCube();
            if (points != null) {
               Console.WriteLine("2D cube: \r\n");
               for(int coordIndex = 0; coordIndex < points.Length; coordIndex++){
                  java.awt.Point target = new  java.awt.Point();
                  drawer.molToScreenCoords(points[coordIndex], target);
                  Console.WriteLine(string.Format( "PixelPoint: {0} {1}", target, coordIndex));
               }
            }
         }


         Console.ReadLine();


 


VB.NET needs to be the same.


Please my answers inline in your question (message).

User 1a8d11549a

22-03-2011 12:04:27

Thanks a lot Victor for your fast response. I am out this afternoon, but should be able to look at your code tomorrow. I'll get back to you ... 

User 1a8d11549a

23-03-2011 07:02:28

Hi Victor,


Thanks a lot for your refined code. It works well, after some modifications to suit my specific needs. Since my initial question was about the bounding rectangles within the Marvin Sketch pane, I prefer to stay with the sketchPane content as a source (also it's easier to check the pixel coordinates for correctness). Also, I apply the same rectangle for the bitmap image and for the maxScale of the MolPrinter. And for some reason I found that this recangle needs to be scaled down by 70% to obtain coordinates corresponding to the actual scale of the marvin sketch content. At least for me, this provided the correct results. Here's the complete code fragment, based on your code:

 // sketchpane is an MSketchPane within a JFrame containing a reaction sketch
chemaxon.struc.RxnMolecule rxnMolecule = (chemaxon.struc.RxnMolecule)sketchPane.getMol()

//Create rectangle for bitmap and maxScale and scale down to 70% to get same size as displayed in MSketchPane (no idea why ....)
java.awt.Rectangle rect = sketchPane.getBounds();
rect.width=7*rect.width/10;
rect.height = 7 * rect.height /10;

// Paint the molecule
nativeImage = new Bitmap(rect.width, rect.height, PixelFormat.Format32bppArgb);
chemaxon.marvin.MolPrinter drawer = new chemaxon.marvin.MolPrinter(rxnMolecule);
drawer.setScale(drawer.maxScale(rect)); // fit image in the rectangle
drawer.paint(new ikvm.awt.BitmapGraphics(nativeImage), rect);

int reactantCount = rxnMolecule.getComponentCount(chemaxon.struc.RxnMolecule.REACTANTS);

for (int index = 0; index < reactantCount; index++)
{
chemaxon.struc.Molecule molecule = rxnMolecule.getComponent    (chemaxon.struc.RxnMolecule.REACTANTS, index);
molecule.setGUIContracted(true);
var points = molecule.getEnclosingCube();
if (points != null)
{
Console.WriteLine("2D cube: \r\n");
for (int coordIndex = 0; coordIndex < points.Length; coordIndex++)
{
java.awt.Point target = new java.awt.Point();
drawer.molToScreenCoords(points[coordIndex], target);
Console.WriteLine(string.Format("PixelPoint: {0} {1}", target, coordIndex));
}
}
}

Again - thanks a lot for the quick and competent solution you provided, based on which I could solve my problem, it's much appreciated!

ChemAxon bd13b5bd77

24-03-2011 14:08:35

Great! If you have further questions please let us know.