1+ from ase .build import fcc111
2+ from autoadsorbate import Fragment , Surface
3+ from ase .io import write
4+ import uuid
5+ import base64
6+
7+ def generate_uid (length = 5 ):
8+ """Generate a short UID from UUID4 using base64 encoding."""
9+ uid = str (uuid .uuid4 ())
10+ # Convert to base64 and take first N characters
11+ encoded = base64 .urlsafe_b64encode (uid .encode ()).decode ()
12+ return encoded [:length ]
13+
14+ def make_smiles_plus (surface , smiles_plus ):
15+
16+ traj = []
17+ for smile in smiles_plus :
18+
19+ fragment = Fragment (smile , to_initialize = fragment_conformers )
20+
21+ traj += surface .get_populated_sites (
22+ fragment ,
23+ site_index = 'all' ,
24+ sample_rotation = True , mode = 'heuristic' ,
25+ conformers_per_site_cap = 5 , overlap_thr = 1.5 , verbose = False
26+ )
27+
28+ out_traj = []
29+ for cation in cations :
30+ for atoms in traj :
31+ a = atoms .copy ()
32+ cf = fragment .get_conformer (0 )
33+ adsorbate_formula = cf [
34+ [atom .index for atom in cf if atom .symbol in ['C' , 'H' , 'O' ]]
35+ ].get_chemical_formula (empirical = True )
36+ a .info ['adsorbate_info' ]['adsorbate_formula' ] = adsorbate_formula
37+ a .info ['adsorbate_info' ]['cation' ] = cation
38+ a [- 1 ].symbol = cation
39+ out_traj += [a ]
40+ return out_traj
41+
42+
43+ def make_smiles (surface , smiles ):
44+
45+ traj = []
46+ for smile in smiles :
47+
48+ fragment = Fragment (smile , to_initialize = fragment_conformers )
49+
50+ traj += surface .get_populated_sites (
51+ fragment ,
52+ site_index = 'all' ,
53+ sample_rotation = True , mode = 'heuristic' ,
54+ conformers_per_site_cap = 5 , overlap_thr = 1.5 , verbose = False
55+ )
56+
57+ for atoms in traj :
58+ atoms .info ['adsorbate_info' ]['cation' ] = 'None'
59+
60+ return traj
61+
62+
63+ def main ():
64+ slab = fcc111 (slab_metal , size = slab_size , vacuum = 10 )
65+ surface = Surface (slab )
66+ surface .sym_reduce ()
67+
68+ out_traj = []
69+ out_traj += make_smiles (surface , smiles )
70+ out_traj += make_smiles_plus (surface , smiles_plus )
71+
72+ for a in out_traj :
73+ a .info ['uid' ] = generate_uid ()
74+
75+ print (f'Writing. . . { len (out_traj ) = } , { out_filename = } ' )
76+ write (out_filename , out_traj )
77+
78+
79+ ###################### user input
80+
81+ slab_metal = 'Cu'
82+ slab_size = [4 ,4 ,4 ]
83+ fragment_conformers = 10
84+ cations = ['Na' ,'K' ,'Li' ,'Cs' ]
85+ out_filename = 'generated_traj.xyz'
86+
87+ smiles = [
88+ 'ClC(=O)[O-]' ,
89+ 'Cl[O+]=C([O-])[O-]' ,
90+ 'ClC(=C=O)[O-]' ,
91+ 'S1SOC([O-])=C1[O-]' ,
92+ ]
93+
94+ smiles_plus = [ #using a similar hack as for the surrogate atom.
95+ 'ClC(=O)OCl' ,
96+ 'Cl[O+]=C(O2)OS2' ,
97+ 'ClC(=C=O)OCl' ,
98+ 'S1SOC(O2)=C1OS2' ,
99+ ]
100+
101+ if __name__ == '__main__' :
102+ main ()
0 commit comments