partridgejiang / Kekule.js

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

loading SMILES #215

Closed sowiso closed 3 years ago

sowiso commented 3 years ago

I'm trying to load a simple molecule in the composer from a SMILES string, but do not really seem to get the desired result. Here's wat I tried:

Kekule.OpenBabel.enable();
let smiles = "C1CCCCC1";
let mol = Kekule.IO.loadFormatData(smiles, "smi");
composer.setChemObj(mol);

This does import, but it does not draw very well. The drawing is so tiny, it's only visible when I select it: image

So I read I could try to generate a 2D sctructure and tried this:

Kekule.OpenBabel.enable();
let smiles = "C1CCCCC1";
let mol = Kekule.IO.loadFormatData(smiles, "smi");
let generator = new Kekule.Calculator.ObStructure2DGenerator();
generator.setSourceMol(mol);
generator.executeSync(function() {
    let newMol = generator.getGeneratedMol();
    composer.setChemObj(newMol);
});

This works better, but now it looks like this: image And the console shows this image

Is there a way to get the smiles = "C1CCCCC1" look like this?

image

Thanks

partridgejiang commented 3 years ago

@sowiso, thanks for the feedback, we have found a bug in ObStructureGenerator.executeSync causing it always returns the 3D structure generated. Currently, as a workaround, please use the execute method rather than executeSync:

Kekule.OpenBabel.enable(() => {
  let smiles = "C1CCCCC1";
  let mol = Kekule.IO.loadFormatData(smiles, "smi");
  let generator = new Kekule.Calculator.ObStructure2DGenerator();
  generator.setSourceMol(mol);
  generator.execute(err => {    // using execute rather than executeSync
    if (!err)
    {
      let newMol = generator.getGeneratedMol();
      composer.setChemObj(newMol);
    }
  });
});

The execute method runs in web worker, so it may even provide a better user experience. By the way, in recent versions, you can also utilize the newly introduced setChemObjData method:

Kekule.OpenBabel.enable(() => {
  composer.getEditor().setChemObjData('{"format": "smi", "data": "C1CCCCC1"}');
});

In default settings, when the editor detects that the input molecule is a 0D one(with out coordinates), it will automatically generate them for the molecule.

sowiso commented 3 years ago

Thanks a lot @partridgejiang I got it to work correctly now with execute(). However, when I call it a second time, it seems like it's not working anymore, whereas executeSync() is.

sowiso commented 3 years ago

It looks like I get a similar behaviour when I load smiles manually via the menu. These steps reproduce the issue:

  1. click "load data", format SMILES, input C1CC1 and click OK
  2. the molecule is now drawn
  3. click "Create new document"
  4. repeat step 1 (click "load data", format SMILES, input C1CC1 and click OK)
  5. the molecule is now not drawn anymore
partridgejiang commented 3 years ago

Hi @sowiso, the bugs in both execute() and executeSync() should be fixed now, please check the latest dist files, :).

sowiso commented 3 years ago

Confirmed, this works perfectly now. Thanks!