Skip to content

Commit

Permalink
Release/1.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
yakutovicha authored Dec 3, 2021
2 parents 0ac4a94 + f4cd2b7 commit 5c188ec
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 19 deletions.
2 changes: 1 addition & 1 deletion aiidalab_widgets_base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@
"viewer",
]

__version__ = "1.1.0"
__version__ = "1.1.1"
6 changes: 3 additions & 3 deletions aiidalab_widgets_base/bug_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def _convert_ansi_codes_to_html(msg):
return converter.produce_headers().strip() + converter.convert(msg, full=False)


def _format_truncated_traceback(traceback, max_num_chars=3000):
def _format_truncated_traceback(traceback, max_num_chars=2000):
"""Truncate the traceback to the given character length."""
n = 0
for i, line in enumerate(reversed(traceback)):
Expand Down Expand Up @@ -145,9 +145,9 @@ def create_github_issue_exception_handler(exception_type, exception, traceback):
exception_type=str(exception_type.__name__)
),
"body": BUG_REPORT_BODY.format(
# Truncate the traceback to a maximum of 3000 characters
# Truncate the traceback to a maximum of 2000 characters
# and strip all ansi control characters:
traceback=_format_truncated_traceback(traceback, 3000),
traceback=_format_truncated_traceback(traceback, 2000),
# Determine and format the environment fingerprint to be
# included with the bug report:
environment_fingerprint="\n".join(
Expand Down
3 changes: 1 addition & 2 deletions aiidalab_widgets_base/databases.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,12 @@ class OptimadeQueryWidget(ipw.VBox):
"cod",
"tcod",
"nmd",
"omdb",
"oqmd",
"aflow",
"matcloud",
"httk",
"mpds",
"necro",
"jarvis",
]
_skip_databases = {"Materials Cloud": ["optimade-sample", "li-ion-conductors"]}
_database_grouping = {
Expand Down
34 changes: 21 additions & 13 deletions aiidalab_widgets_base/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,12 @@ def _convert_to_structure_node(self, structure):

# If the input_structure trait is set to Atoms object, structure node must be created from it.
if isinstance(structure, Atoms):
return structure_node_type(ase=structure)
# If the Atoms object was created by SmilesWidget,
# attach its SMILES code as an extra.
structure_node = structure_node_type(ase=structure)
if "smiles" in structure.info:
structure_node.set_extra("smiles", structure.info["smiles"])
return structure_node

# If the input_structure trait is set to AiiDA node, check what type
if isinstance(structure, Data):
Expand Down Expand Up @@ -653,25 +658,28 @@ def __init__(self, title=""):

super().__init__([self.smiles, self.create_structure_btn, self.output])

def make_ase(self, species, positions):
def _make_ase(self, species, positions, smiles):
"""Create ase Atoms object."""
# Get the principal axes and realign the molecule along z-axis.
positions = PCA(n_components=3).fit_transform(positions)
atoms = Atoms(species, positions=positions, pbc=True)
atoms.cell = np.ptp(atoms.positions, axis=0) + 10
atoms.center()
# We're attaching this info so that it
# can be later stored as an extra on AiiDA Structure node.
atoms.info["smiles"] = smiles

return atoms

def _pybel_opt(self, smile, steps):
def _pybel_opt(self, smiles, steps):
"""Optimize a molecule using force field and pybel (needed for complex SMILES)."""
from openbabel import openbabel as ob
from openbabel import pybel as pb

obconversion = ob.OBConversion()
obconversion.SetInFormat("smi")
obmol = ob.OBMol()
obconversion.ReadString(obmol, smile)
obconversion.ReadString(obmol, smiles)

pbmol = pb.Molecule(obmol)
pbmol.make3D(forcefield="uff", steps=50)
Expand All @@ -685,30 +693,30 @@ def _pybel_opt(self, smile, steps):
f_f.GetCoordinates(pbmol.OBMol)
species = [chemical_symbols[atm.atomicnum] for atm in pbmol.atoms]
positions = np.asarray([atm.coords for atm in pbmol.atoms])
return self.make_ase(species, positions)
return self._make_ase(species, positions, smiles)

def _rdkit_opt(self, smile, steps):
def _rdkit_opt(self, smiles, steps):
"""Optimize a molecule using force field and rdkit (needed for complex SMILES)."""
from rdkit import Chem
from rdkit.Chem import AllChem

smile = smile.replace("[", "").replace("]", "")
mol = Chem.MolFromSmiles(smile)
smiles = smiles.replace("[", "").replace("]", "")
mol = Chem.MolFromSmiles(smiles)
mol = Chem.AddHs(mol)

AllChem.EmbedMolecule(mol, maxAttempts=20, randomSeed=42)
AllChem.UFFOptimizeMolecule(mol, maxIters=steps)
positions = mol.GetConformer().GetPositions()
natoms = mol.GetNumAtoms()
species = [mol.GetAtomWithIdx(j).GetSymbol() for j in range(natoms)]
return self.make_ase(species, positions)
return self._make_ase(species, positions, smiles)

def mol_from_smiles(self, smile, steps=10000):
def _mol_from_smiles(self, smiles, steps=10000):
"""Convert SMILES to ase structure try rdkit then pybel"""
try:
return self._rdkit_opt(smile, steps)
return self._rdkit_opt(smiles, steps)
except ValueError:
return self._pybel_opt(smile, steps)
return self._pybel_opt(smiles, steps)

def _on_button_pressed(self, change): # pylint: disable=unused-argument
"""Convert SMILES to ase structure when button is pressed."""
Expand All @@ -719,7 +727,7 @@ def _on_button_pressed(self, change): # pylint: disable=unused-argument
self.output.value = "Screening possible conformers {}".format(
self.SPINNER
) # font-size:20em;
self.structure = self.mol_from_smiles(self.smiles.value)
self.structure = self._mol_from_smiles(self.smiles.value)
self.output.value = ""

@default("structure")
Expand Down

0 comments on commit 5c188ec

Please sign in to comment.