partridgejiang / Kekule.js

A Javascript cheminformatics toolkit.
http://partridgejiang.github.io/Kekule.js
MIT License
248 stars 61 forks source link

draw reaction from smiles #31

Open rmrmg opened 6 years ago

rmrmg commented 6 years ago

How can I display reaction from smiles (e.g. CCO.C(=O)O>>C(=O)OCC )in Viewer2D? As I can see it is not possible to export/import it directly from smiles. My first idea is: a) export each mol to kcj, b) edit coordinates (move each atom), c) add plus signs and narrow; d) save to kcj and load such file. Do you have any better idea?

partridgejiang commented 6 years ago

Your idea is the best practicable way so far. However, instead of setting coordinate of atoms, the molecule itself also has coordinate property, you can set it directly: mol.setCoord2D({x: xvalue, y: yvalue})

rmrmg commented 6 years ago

@partridgejiang: Thx for the answer. I have tried to play with mol.setCoord2d but I dont understand it behavior - a cannot get anything reasonable. Could you, please, show the code used to generate the whole reaction (with plus, narrow, catalyst and text) presented here: https://partridgejiang.github.io/Kekule.js/documents/tutorial/examples/composer.html this will be, in my opinion, a great tutorial.

partridgejiang commented 6 years ago

In a simple way, the coordinate of a molecule object is an offset for all its child atoms. For example, suppose we have a HCl molecule, the coordinate of H is set to {x: 1, y: 1} and of Cl is {x: 2, y2}, and the coordinate of the molecule is {x: 10, y: 10}. Then the real position of H is {x: 11, y: 11} and of Cl is {x: 12, y: 12}. So simple set the coordinate of a molecule can do a position translation for all its children.

rmrmg commented 6 years ago

@partridgejiang: Thx for explanation. What about "+" and reaction arrow? Is it possible to create mol with plus and reaction narrow?

partridgejiang commented 6 years ago

@rmrmg The plus symbol is represented by Kekule.Glyph.AddSymbol, and the arrow is represented by Kekule.Glyph.StraightLine (with initialParams property set to {'endArrowType': Kekule.Glyph.ArrowType.OPEN} when being created). However, drawing a reaction involves in a lot complex works (e.g. transform between screen coordinate system and molecule internal coordinate system).

So if you merely want to display a reaction on HTML page, a much simple approach can be used instead. Several autosized ChemViewer widget can be used to display reactant and product molecules and standard HTML <span> element can be used to display plus and arrow symbol. The following codes may provide a sample for you:

<style>
  /* ensure all molecules and symbols are aligned to the middle */
  #reaction { vertical-align: middle }
  .reactionMember { display: inline-block}
</style>
<p id="reaction"></p>
<script>
  function addSymbol(symbol, parentElem)  // add "+" or "⟶" to reaction
  {
    var elem = document.createElement('span');
    elem.className = 'reactionMember ';
    elem.innerHTML = symbol;
    parentElem.appendChild(elem);
  }
  function addReagent(molecule, parentElem)  // add single molecule to reaction
  {
    var viewer = new Kekule.ChemWidget.Viewer2D(document, molecule);
    viewer.setAutoSize(true).setPredefinedSetting('static').addClassName('reactionMember');
    viewer.appendToElem(parentElem);
  }  
  function displayReaction(reactants, products)  // display the whole reaction
  {
    var parentElem = document.getElementById('reaction');
    // reactants on the left
    for (var i = 0, l = reactants.length; i < ; ++i)
    {
      if ( i > 0)
        addSysmbol('+', parentElem);
      addReagent(reactants[i]);
    }
    // the reaction arrow
    addSymbol('⟶', parentElem);
    // products on the right
    for (var i = 0, l = products.length; i < ; ++i)
    {
      if ( i > 0)
        addSysmbol('+', parentElem);
      addReagent(products[i]);
    }
  }
</script>