Skip to content

Commit b9c7cfc

Browse files
committed
If adsorbate site drawing causes problems, do it without.
If two surface sites overlap, or if a site-adatom bond is too long, then give up on the fancy algorithm, and just let RDkit place the X atoms wherever, without them being bonded.
1 parent dfcfa06 commit b9c7cfc

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

rmgpy/molecule/draw.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import math
5050
import os.path
5151
import re
52+
import itertools
5253

5354
try:
5455
import cairocffi as cairo
@@ -97,6 +98,12 @@ def create_new_surface(file_format, target=None, width=1024, height=768):
9798

9899
################################################################################
99100

101+
class AdsorbateDrawingError(Exception):
102+
"""
103+
When something goes wrong trying to draw an adsorbate.
104+
"""
105+
pass
106+
100107
class MoleculeDrawer(object):
101108
"""
102109
This class provides functionality for drawing the skeletal formula of
@@ -209,9 +216,13 @@ def draw(self, molecule, file_format, target=None):
209216
# bugs with RDKit
210217
old_bond_dictionary = self._make_single_bonds()
211218
if molecule.contains_surface_site():
212-
self._connect_surface_sites()
213-
self._generate_coordinates()
214-
self._disconnect_surface_sites()
219+
try:
220+
self._connect_surface_sites()
221+
self._generate_coordinates()
222+
self._disconnect_surface_sites()
223+
except AdsorbateDrawingError as e:
224+
self._disconnect_surface_sites()
225+
self._generate_coordinates(fix_surface_sites=False)
215226
else:
216227
self._generate_coordinates()
217228
self._replace_bonds(old_bond_dictionary)
@@ -329,11 +340,13 @@ def _find_ring_groups(self):
329340
if not found:
330341
self.ringSystems.append([cycle])
331342

332-
def _generate_coordinates(self):
343+
def _generate_coordinates(self, fix_surface_sites=True):
333344
"""
334345
Generate the 2D coordinates to be used when drawing the current
335346
molecule. The function uses rdKits 2D coordinate generation.
336347
Updates the self.coordinates Array in place.
348+
If `fix_surface_sites` is True, then the surface sites are placed
349+
at the bottom of the molecule.
337350
"""
338351
atoms = self.molecule.atoms
339352
natoms = len(atoms)
@@ -464,7 +477,7 @@ def _generate_coordinates(self):
464477
coordinates[:, 1] = temp[:, 0]
465478

466479
# For surface species
467-
if self.molecule.contains_surface_site():
480+
if fix_surface_sites and self.molecule.contains_surface_site():
468481
if len(self.molecule.atoms) == 1:
469482
return coordinates
470483
sites = [atom for atom in self.molecule.atoms if atom.is_surface_site()]
@@ -503,10 +516,16 @@ def _generate_coordinates(self):
503516
x = coordinates[adatom_indices, 0]
504517
y = coordinates[adatom_indices, 1]
505518
site_y_pos = min(min(y) - 0.8, min(coordinates[not_site_indices, 1]) - 0.5)
519+
if max(y) - site_y_pos > 1.5:
520+
raise AdsorbateDrawingError("Adsorbate bond too long")
521+
for x1, x2 in itertools.combinations(x, 2):
522+
if abs(x1 - x2) < 0.2:
523+
raise AdsorbateDrawingError("Sites overlapping")
506524
for site, x_pos in zip(sites, x):
507525
index = atoms.index(site)
508526
coordinates[index, 1] = site_y_pos
509527
coordinates[index, 0] = x_pos
528+
510529
else:
511530
# more than 4 surface sites? leave them alone
512531
pass

0 commit comments

Comments
 (0)