rdworks 0.25.8__py3-none-any.whl → 0.36.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rdworks/units.py CHANGED
@@ -1,63 +1,12 @@
1
- from types import SimpleNamespace
2
-
3
1
  # In ASE, the default energy unit is eV (electron volt).
4
- # It will be converted to kcal/mol
5
- #CODATA 2018 energy conversion factor
2
+ # In xtb, the default energy unit it Eh (hartree).
3
+
4
+ # CODATA 2018 energy conversion factor
5
+
6
6
  hartree2ev = 27.211386245988
7
7
  hartree2kcalpermol = 627.50947337481
8
8
  ev2kcalpermol = 23.060547830619026
9
9
 
10
- periodictable = SimpleNamespace(
11
- symbol = {
12
- 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne',
13
- 11: 'Na', 12: 'Mg', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', 20: 'Ca',
14
- 21: 'Sc', 22: 'Ti', 23: 'V', 24: 'Cr', 25: 'Mn', 26: 'Fe', 27: 'Co', 28: 'Ni', 29: 'Cu', 30: 'Zn',
15
- 31: 'Ga', 32: 'Ge', 33: 'As', 34: 'Se', 35: 'Br', 36: 'Kr', 37: 'Rb', 38: 'Sr', 39: 'Y', 40: 'Zr',
16
- 41: 'Nb', 42: 'Mo', 43: 'Tc', 44: 'Ru', 45: 'Rh', 46: 'Pd', 47: 'Ag', 48: 'Cd', 49: 'In', 50: 'Sn',
17
- 51: 'Sb', 52: 'Te', 53: 'I', 54: 'Xe', 55: 'Cs', 56: 'Ba', 57: 'La', 58: 'Ce', 59: 'Pr', 60: 'Nd',
18
- 61: 'Pm', 62: 'Sm', 63: 'Eu', 64: 'Gd', 65: 'Tb', 66: 'Dy', 67: 'Ho', 68: 'Er', 69: 'Tm', 70: 'Yb',
19
- 71: 'Lu', 72: 'Hf', 73: 'Ta', 74: 'W', 75: 'Re', 76: 'Os', 77: 'Ir', 78: 'Pt', 79: 'Au', 80: 'Hg',
20
- 81: 'Tl', 82: 'Pb', 83: 'Bi', 84: 'Po', 85: 'At', 86: 'Rn', 87: 'Fr', 88: 'Ra', 89: 'Ac', 90: 'Th',
21
- 91: 'Pa', 92: 'U', 93: 'Np', 94: 'Pu', 95: 'Am', 96: 'Cm', 97: 'Bk', 98: 'Cf', 99: 'Es', 100: 'Fm',
22
- 101: 'Md', 102: 'No', 103: 'Lr', 104: 'Rf', 105: 'Db', 106: 'Sg', 107: 'Bh', 108: 'Hs', 109: 'Mt', 110: 'Ds',
23
- 111: 'Rg', 112: 'Cn', 113: 'Nh', 114: 'Fl', 115: 'Mc', 116: 'Lv', 117: 'Ts', 118: 'Og'
24
- },
25
- long_symbol = {
26
- 1: 'Hydrogen', 2: 'Helium', 3: 'Lithium', 4: 'Beryllium', 5: 'Boron',
27
- 6: 'Carbon', 7: 'Nitrogen', 8: 'Oxygen', 9: 'Fluorine', 10: 'Neon',
28
- 11: 'Sodium', 12: 'Magnesium', 13: 'Aluminum', 14: 'Silicon', 15: 'Phosphorus',
29
- 16: 'Sulfur', 17: 'Chlorine', 18: 'Argon', 19: 'Potassium', 20: 'Calcium',
30
- 21: 'Scandium', 22: 'Titanium', 23: 'Vanadium', 24: 'Chromium', 25: 'Manganese',
31
- 26: 'Iron', 27: 'Cobalt', 28: 'Nickel', 29: 'Copper', 30: 'Zinc',
32
- 31: 'Gallium', 32: 'Germanium', 33: 'Arsenic', 34: 'Selenium', 35: 'Bromine',
33
- 36: 'Krypton', 37: 'Rubidium', 38: 'Strontium', 39: 'Yttrium', 40: 'Zirconium',
34
- 41: 'Niobium', 42: 'Molybdenum', 43: 'Technetium', 44: 'Ruthenium', 45: 'Rhodium',
35
- 46: 'Palladium', 47: 'Silver', 48: 'Cadmium', 49: 'Indium', 50: 'Tin',
36
- 51: 'Antimony', 52: 'Tellurium', 53: 'Iodine', 54: 'Xenon', 55: 'Cesium',
37
- 56: 'Barium', 57: 'Lanthanum', 58: 'Cerium', 59: 'Praseodymium', 60: 'Neodymium',
38
- 61: 'Promethium', 62: 'Samarium', 63: 'Europium', 64: 'Gadolinium', 65: 'Terbium',
39
- 66: 'Dysprosium', 67: 'Holmium', 68: 'Erbium', 69: 'Thulium', 70: 'Ytterbium',
40
- 71: 'Lutetium', 72: 'Hafnium', 73: 'Tantalum', 74: 'Tungsten', 75: 'Rhenium',
41
- 76: 'Osmium', 77: 'Iridium', 78: 'Platinum', 79: 'Gold', 80: 'Mercury',
42
- 81: 'Thallium', 82: 'Lead', 83: 'Bismuth', 84: 'Polonium', 85: 'Astatine',
43
- 86: 'Radon', 87: 'Francium', 88: 'Radium', 89: 'Actinium', 90: 'Thorium',
44
- 91: 'Protactinium', 92: 'Uranium', 93: 'Neptunium', 94: 'Plutonium', 95: 'Americium',
45
- 96: 'Curium', 97: 'Berkelium', 98: 'Californium', 99: 'Einsteinium', 100: 'Fermium',
46
- 101: 'Mendelevium', 102: 'Nobelium', 103: 'Lawrencium', 104: 'Rutherfordium', 105: 'Dubnium',
47
- 106: 'Seaborgium', 107: 'Bohrium', 108: 'Hassium', 109: 'Meitnerium', 110: 'Darmstadtium',
48
- 111: 'Roentgenium', 112: 'Copernicium', 113: 'Nihonium', 114: 'Flerovium', 115: 'Moscovium',
49
- 116: 'Livermorium', 117: 'Tennessine', 118: 'Oganesson'
50
- },
51
- )
52
-
53
-
54
- # Initialize UFF bond radii (Rappe et al. JACS 1992)
55
- # Units of angstroms
56
- # These radii neglect the bond-order and electronegativity corrections in the original paper.
57
- # Where several values exist for the same atom, the largest was used.
58
- radii = {
59
- 1:0.354, 5:0.838, 6:0.757, 7:0.700, 8:0.658, 9:0.668,
60
- 14:1.117, 15:1.117, 16:1.064, 17:1.044,
61
- 32:1.197, 33:1.211, 34:1.190, 35:1.192,
62
- 51:1.407, 52:1.386, 53:1.382,
63
- }
10
+ # In mendeleev, the default length unit is pm.
11
+ # picometer (e-12) to angstrom (e-10)
12
+ pm2angstrom = 0.01
rdworks/utils.py CHANGED
@@ -1,18 +1,16 @@
1
1
  import numpy as np
2
2
  import math
3
- import networkx as nx
4
- import gzip
5
3
  import operator
6
- import re
7
- import shlex
8
4
 
9
- from rdkit import Chem
10
5
  from pathlib import Path
11
- from typing import Any, Callable
12
- from functools import reduce
6
+ from types import SimpleNamespace
7
+ from typing import Any
8
+ from collections.abc import Callable
13
9
  from concurrent.futures import ProcessPoolExecutor
14
10
  from tqdm import tqdm
15
11
 
12
+ from rdkit import Chem
13
+
16
14
  from rdworks.autograph.centroid import centroid_medoid
17
15
 
18
16
 
@@ -96,13 +94,47 @@ def guess_mol_id(lprops:list[dict]) -> tuple[str, int, int]:
96
94
  return (property_key, count, total)
97
95
 
98
96
 
97
+ def dict_to_simplenamespace(data):
98
+ if isinstance(data, dict):
99
+ return SimpleNamespace(**{k: dict_to_simplenamespace(v) for k, v in data.items()})
100
+ elif isinstance(data, list):
101
+ return [dict_to_simplenamespace(item) for item in data]
102
+ else:
103
+ return data
104
+
105
+
106
+ def recursive_round(data:Any, decimals:int=2) -> Any:
107
+ """Recursively round float values to a given decimal places.
99
108
 
100
- def fix_decimal_places_in_list(in_list:list, decimal_places:int=2) -> list:
109
+ Args:
110
+ data: The input data, which can be a list, dictionary, or any
111
+ other data type. It can contain nested lists and dictionaries.
112
+ decimals: number of decimal places.
113
+ """
114
+ if not isinstance(decimals, int) or decimals < 0:
115
+ raise ValueError("decimals must be a non-negative integer.")
116
+
117
+ def _recursive_round(current_item):
118
+ if isinstance(current_item, float):
119
+ return round(current_item, decimals)
120
+ elif isinstance(current_item, np.float64):
121
+ return round(float(current_item), decimals)
122
+ elif isinstance(current_item, list):
123
+ return [_recursive_round(item) for item in current_item]
124
+ elif isinstance(current_item, dict):
125
+ return {key: _recursive_round(value) for key, value in current_item.items()}
126
+ else:
127
+ return current_item
128
+
129
+ return _recursive_round(data)
130
+
131
+
132
+ def fix_decimals_in_list(in_list:list, decimals:int=2) -> list:
101
133
  """Fixes the decimal places of all float values in a list.
102
134
 
103
135
  Args:
104
136
  list: The list to fix.
105
- decimal_places (int): The number of decimal places to fix the float values to.
137
+ decimals (int): The number of decimal places to fix the float values to.
106
138
 
107
139
  Returns:
108
140
  list: a list with the float values fixed to the specified number of decimal places.
@@ -111,22 +143,22 @@ def fix_decimal_places_in_list(in_list:list, decimal_places:int=2) -> list:
111
143
  out_list = []
112
144
  for item in in_list:
113
145
  if isinstance(item, float):
114
- out_list.append(round(item, decimal_places))
146
+ out_list.append(round(item, decimals))
115
147
  elif isinstance(item, dict):
116
- out_list.append(fix_decimal_places_in_dict(item, decimal_places))
148
+ out_list.append(fix_decimals_in_dict(item, decimals))
117
149
  elif isinstance(item, list) or isinstance(item, tuple):
118
- out_list.append(fix_decimal_places_in_list(item, decimal_places))
150
+ out_list.append(fix_decimals_in_list(item, decimals))
119
151
  else:
120
152
  out_list.append(item)
121
153
  return out_list
122
154
 
123
155
 
124
- def fix_decimal_places_in_dict(in_dict:dict, decimal_places:int=2) -> dict:
156
+ def fix_decimals_in_dict(in_dict:dict, decimals:int=2) -> dict:
125
157
  """Fixes the decimal places of all float values in a dictionary.
126
158
 
127
159
  Args:
128
160
  dictionary: The dictionary to fix.
129
- decimal_places (int): The number of decimal places to fix the float values to.
161
+ decimals (int): The number of decimal places to fix the float values to.
130
162
 
131
163
  Returns:
132
164
  dict: a dictionary with the float values fixed to the specified number of decimal places.
@@ -134,11 +166,11 @@ def fix_decimal_places_in_dict(in_dict:dict, decimal_places:int=2) -> dict:
134
166
  out_dict = {}
135
167
  for k, v in in_dict.items():
136
168
  if isinstance(v, float):
137
- out_dict[k] = round(v, decimal_places)
169
+ out_dict[k] = round(v, decimals)
138
170
  elif isinstance(v, list) or isinstance(v, tuple):
139
- out_dict[k] = fix_decimal_places_in_list(v, decimal_places)
171
+ out_dict[k] = fix_decimals_in_list(v, decimals)
140
172
  elif isinstance(v, dict):
141
- out_dict[k] = fix_decimal_places_in_dict(v, decimal_places)
173
+ out_dict[k] = fix_decimals_in_dict(v, decimals)
142
174
  else:
143
175
  out_dict[k] = v
144
176
  return out_dict
@@ -252,244 +284,95 @@ def QT(rmsd_matrix:np.ndarray, threshold:float) -> tuple:
252
284
  return cluster_assignment, centroid_indices
253
285
 
254
286
 
255
- def rdmol_to_graph(rdmol:Chem.Mol) -> nx.Graph:
256
- """Converts rdkit.Chem.Mol to a networkx graph object.
257
-
258
- Args:
259
- rdmol (Chem.Mol): input molecule.
260
-
261
- Returns:
262
- nx.Graph: networkx graph object.
263
- """
264
- G = nx.Graph()
265
- for atom in rdmol.GetAtoms():
266
- G.add_node(atom.GetIdx(), # 0-based index
267
- atomic_num=atom.GetAtomicNum(),
268
- formal_charge=atom.GetFormalCharge(),
269
- chiral_tag=atom.GetChiralTag(),
270
- hybridization=atom.GetHybridization(),
271
- num_explicit_hs=atom.GetNumExplicitHs(),
272
- is_aromatic=atom.GetIsAromatic())
273
- for bond in rdmol.GetBonds():
274
- G.add_edge(bond.GetBeginAtomIdx(),
275
- bond.GetEndAtomIdx(),
276
- bond_type=bond.GetBondType())
277
- return G
278
-
279
-
280
- def rdmol_to_graph_(rdmol:Chem.Mol) -> nx.Graph:
281
- """Converts rdkit.Chem.Mol to a networkx graph object (another implementation).
282
-
283
- Args:
284
- rdmol (Chem.Mol): input molecule.
285
-
286
- Returns:
287
- nx.Graph: networkx graph object.
288
- """
289
- atomic_nums = [atom.GetAtomicNum() for atom in rdmol.GetAtoms()]
290
- formal_charges = [atom.GetFormalCharge() for atom in rdmol.GetAtoms()]
291
- ad_matrix = Chem.GetAdjacencyMatrix(rdmol, useBO=True)
292
- # useBO: (optional) toggles use of bond orders in calculating the matrix. Default value is 0.
293
- # RETURNS: a Numeric array of floats containing the adjacency matrix
294
- # [[0. 1. 0. 0. 0. 0. 0. 0. 0.]
295
- # [1. 0. 1. 1. 1. 0. 0. 0. 0.]
296
- # [0. 1. 0. 0. 0. 0. 0. 0. 0.]
297
- # [0. 1. 0. 0. 0. 0. 0. 0. 0.]
298
- # [0. 1. 0. 0. 0. 1. 0. 1. 0.]
299
- # [0. 0. 0. 0. 1. 0. 2. 0. 0.]
300
- # [0. 0. 0. 0. 0. 2. 0. 0. 0.]
301
- # [0. 0. 0. 0. 1. 0. 0. 0. 2.]
302
- # [0. 0. 0. 0. 0. 0. 0. 2. 0.]]
303
- for i,(a_num,f_c) in enumerate(zip(atomic_nums, formal_charges)):
304
- if f_c !=0:
305
- ad_matrix[i,i] = a_num + f_c
306
- else:
307
- ad_matrix[i,i] = a_num
308
- G = nx.from_numpy_array(ad_matrix)
309
- return G
310
-
311
-
312
- def graph_to_rdmol(G:nx.Graph) -> Chem.Mol:
313
- """Converts a networkx graph object to rdkit.Chem.Mol object.
314
-
315
- Args:
316
- G (nx.Graph): a networkx graph.
317
-
318
- Returns:
319
- Chem.Mol: rdkit.Chem.Mol object.
320
- """
321
- rdmol = Chem.RWMol()
322
- atomic_nums = nx.get_node_attributes(G, 'atomic_num')
323
- chiral_tags = nx.get_node_attributes(G, 'chiral_tag')
324
- formal_charges = nx.get_node_attributes(G, 'formal_charge')
325
- node_is_aromatics = nx.get_node_attributes(G, 'is_aromatic')
326
- node_hybridizations = nx.get_node_attributes(G, 'hybridization')
327
- num_explicit_hss = nx.get_node_attributes(G, 'num_explicit_hs')
328
- node_to_idx = {}
329
- for node in G.nodes():
330
- a=Chem.Atom(atomic_nums[node])
331
- a.SetChiralTag(chiral_tags[node])
332
- a.SetFormalCharge(formal_charges[node])
333
- a.SetIsAromatic(node_is_aromatics[node])
334
- a.SetHybridization(node_hybridizations[node])
335
- a.SetNumExplicitHs(num_explicit_hss[node])
336
- idx = rdmol.AddAtom(a)
337
- node_to_idx[node] = idx
338
- bond_types = nx.get_edge_attributes(G, 'bond_type')
339
- for edge in G.edges():
340
- first, second = edge
341
- ifirst = node_to_idx[first]
342
- isecond = node_to_idx[second]
343
- bond_type = bond_types[first, second]
344
- rdmol.AddBond(ifirst, isecond, bond_type)
345
- Chem.SanitizeMol(rdmol)
346
- return rdmol
347
-
348
-
349
- def mae_rd_index(mol_dict:dict, smiles:str) -> dict:
350
- """Returns a map for atom indexes between a rdkit.Chem.Mol and a maestro file.
351
-
352
- It uses networkx's `vf2pp_all_isomorphisms()` function.
353
-
354
- Args:
355
- mol_dict (dict): a dictionary generated from a maestro file.
356
- smiles (str): SMILES of the molecule.
357
-
358
- Returns:
359
- dict: a map for atom indexes (maestro -> rdkit.Chem.Mol)
360
- """
361
- bond_order_map = {
362
- Chem.BondType.SINGLE : 1.0,
363
- Chem.BondType.DOUBLE : 2.0,
364
- Chem.BondType.TRIPLE : 3.0,
365
- Chem.BondType.AROMATIC : 1.5,
366
- Chem.BondType.UNSPECIFIED : 0.0,
367
- }
368
-
369
- G = nx.Graph()
370
- for idx, atomic_num in enumerate(mol_dict['f_m_ct']['m_atom']['i_m_atomic_number'], start=1):
371
- G.add_node(idx, atomic_num=int(atomic_num))
372
- for (bond_from, bond_to, bond_order) in zip(mol_dict['f_m_ct']['m_bond']['i_m_from'],
373
- mol_dict['f_m_ct']['m_bond']['i_m_to'],
374
- mol_dict['f_m_ct']['m_bond']['i_m_order']):
375
- G.add_edge(int(bond_from), int(bond_to), bond_order=int(bond_order))
376
-
377
- H = nx.Graph()
378
- rdmol = Chem.MolFromSmiles(smiles)
379
- rdmol = Chem.AddHs(rdmol)
380
- for atom in rdmol.GetAtoms():
381
- H.add_node(atom.GetIdx(), atomic_num=atom.GetAtomicNum())
382
- for bond in rdmol.GetBonds():
383
- H.add_edge(bond.GetBeginAtomIdx(),
384
- bond.GetEndAtomIdx(),
385
- bond_order=bond_order_map[bond.GetBondType()])
386
-
387
- try:
388
- assert nx.is_isomorphic(G, H)
389
- return nx.vf2pp_isomorphism(G, H, node_label="atomic_num")
390
- except:
391
- return {}
392
-
393
-
394
- def _get_from_dict(dataDict:dict, mapList:list) -> None:
395
- """A subroutine for `mae_to_dict()`.
396
-
397
- Args:
398
- dataDict (dict): data dictionary.
399
- mapList (list): map list.
400
- """
401
- return reduce(operator.getitem, mapList, dataDict)
402
-
403
-
404
- def _set_in_dict(dataDict:dict, mapList:list, value:Any) -> None:
405
- """A subroutine for `mae_to_dict()`.
406
-
407
- Args:
408
- dataDict (dict): data dictionary.
409
- mapList (list): map list.
410
- value (Any): value to set.
411
- """
412
- if mapList:
413
- _get_from_dict(dataDict, mapList[:-1])[mapList[-1]] = value
414
- else:
415
- for k,v in value.items():
416
- dataDict[k] = v
417
-
418
-
419
-
420
- def mae_to_dict(path:str | Path) -> dict:
421
- """Converts Schrodinger Maestro file to a dictionary.
422
-
423
- Args:
424
- path (Union[str, Path]): filename or path to a .mae or .maegz file.
425
-
426
- Returns:
427
- dict: python dictionary.
428
- """
429
- tokens = None
430
- if isinstance(path, str):
431
- path = Path(path)
432
- if path.suffix == 'gz':
433
- with gzip.open(path, "rt") as f:
434
- tokens = shlex.split(f.read())
435
- else:
436
- with open(path, "r") as f:
437
- tokens = shlex.split(f.read())
438
- count = re.compile(r'(\w+)\[(\d+)\]')
439
- DATA = []
440
- level = []
441
- data = {}
442
- previous_token = None
443
- header = False
444
- extra_column = 0
445
- num_repeat = 1
446
- skip = False
447
- for token in tokens :
448
- if token == "#" :
449
- skip = not skip # invert
450
- continue
451
- elif skip:
452
- continue
453
- elif token == "{" :
454
- header = True
455
- key = []
456
- val = []
457
- arr = []
458
- if previous_token:
459
- if previous_token == "f_m_ct" and data:
460
- DATA.append(data)
461
- data = {}
462
- try:
463
- (block, num_repeat) = count.findall(previous_token)[0]
464
- num_repeat = int(num_repeat)
465
- extra_column = 1
466
- except:
467
- block = previous_token
468
- num_repeat = 1
469
- extra_column = 0
470
- level.append(block)
471
-
472
- elif token == "}":
473
- if level:
474
- level.pop()
475
- elif token == ":::":
476
- header = False
477
- elif header:
478
- key.append(token)
479
- else:
480
- val.append(token)
481
- # only store f_m_ct blocks (level != [])
482
- if len(val) == (len(key)+extra_column) and level :
483
- arr.append(val[extra_column:])
484
- val = []
485
- if len(arr) == num_repeat:
486
- if len(arr) == 1:
487
- _set_in_dict(data, level, dict(zip(key,arr[0])))
488
- else:
489
- T = list(zip(*arr)) # transpose
490
- _set_in_dict(data, level, dict(zip(key,T)))
491
- previous_token = token
492
- if data:
493
- DATA.append(data)
494
-
495
- return DATA
287
+ # def rdmol_to_graph(rdmol:Chem.Mol) -> nx.Graph:
288
+ # """Converts rdkit.Chem.Mol to a networkx graph object.
289
+
290
+ # Args:
291
+ # rdmol (Chem.Mol): input molecule.
292
+
293
+ # Returns:
294
+ # nx.Graph: networkx graph object.
295
+ # """
296
+ # G = nx.Graph()
297
+ # for atom in rdmol.GetAtoms():
298
+ # G.add_node(atom.GetIdx(), # 0-based index
299
+ # atomic_num=atom.GetAtomicNum(),
300
+ # formal_charge=atom.GetFormalCharge(),
301
+ # chiral_tag=atom.GetChiralTag(),
302
+ # hybridization=atom.GetHybridization(),
303
+ # num_explicit_hs=atom.GetNumExplicitHs(),
304
+ # is_aromatic=atom.GetIsAromatic())
305
+ # for bond in rdmol.GetBonds():
306
+ # G.add_edge(bond.GetBeginAtomIdx(),
307
+ # bond.GetEndAtomIdx(),
308
+ # bond_type=bond.GetBondType())
309
+ # return G
310
+
311
+
312
+ # def rdmol_to_graph_(rdmol:Chem.Mol) -> nx.Graph:
313
+ # """Converts rdkit.Chem.Mol to a networkx graph object (another implementation).
314
+
315
+ # Args:
316
+ # rdmol (Chem.Mol): input molecule.
317
+
318
+ # Returns:
319
+ # nx.Graph: networkx graph object.
320
+ # """
321
+ # atomic_nums = [atom.GetAtomicNum() for atom in rdmol.GetAtoms()]
322
+ # formal_charges = [atom.GetFormalCharge() for atom in rdmol.GetAtoms()]
323
+ # ad_matrix = Chem.GetAdjacencyMatrix(rdmol, useBO=True)
324
+ # # useBO: (optional) toggles use of bond orders in calculating the matrix. Default value is 0.
325
+ # # RETURNS: a Numeric array of floats containing the adjacency matrix
326
+ # # [[0. 1. 0. 0. 0. 0. 0. 0. 0.]
327
+ # # [1. 0. 1. 1. 1. 0. 0. 0. 0.]
328
+ # # [0. 1. 0. 0. 0. 0. 0. 0. 0.]
329
+ # # [0. 1. 0. 0. 0. 0. 0. 0. 0.]
330
+ # # [0. 1. 0. 0. 0. 1. 0. 1. 0.]
331
+ # # [0. 0. 0. 0. 1. 0. 2. 0. 0.]
332
+ # # [0. 0. 0. 0. 0. 2. 0. 0. 0.]
333
+ # # [0. 0. 0. 0. 1. 0. 0. 0. 2.]
334
+ # # [0. 0. 0. 0. 0. 0. 0. 2. 0.]]
335
+ # for i,(a_num,f_c) in enumerate(zip(atomic_nums, formal_charges)):
336
+ # if f_c !=0:
337
+ # ad_matrix[i,i] = a_num + f_c
338
+ # else:
339
+ # ad_matrix[i,i] = a_num
340
+ # G = nx.from_numpy_array(ad_matrix)
341
+ # return G
342
+
343
+
344
+ # def graph_to_rdmol(G:nx.Graph) -> Chem.Mol:
345
+ # """Converts a networkx graph object to rdkit.Chem.Mol object.
346
+
347
+ # Args:
348
+ # G (nx.Graph): a networkx graph.
349
+
350
+ # Returns:
351
+ # Chem.Mol: rdkit.Chem.Mol object.
352
+ # """
353
+ # rdmol = Chem.RWMol()
354
+ # atomic_nums = nx.get_node_attributes(G, 'atomic_num')
355
+ # chiral_tags = nx.get_node_attributes(G, 'chiral_tag')
356
+ # formal_charges = nx.get_node_attributes(G, 'formal_charge')
357
+ # node_is_aromatics = nx.get_node_attributes(G, 'is_aromatic')
358
+ # node_hybridizations = nx.get_node_attributes(G, 'hybridization')
359
+ # num_explicit_hss = nx.get_node_attributes(G, 'num_explicit_hs')
360
+ # node_to_idx = {}
361
+ # for node in G.nodes():
362
+ # a=Chem.Atom(atomic_nums[node])
363
+ # a.SetChiralTag(chiral_tags[node])
364
+ # a.SetFormalCharge(formal_charges[node])
365
+ # a.SetIsAromatic(node_is_aromatics[node])
366
+ # a.SetHybridization(node_hybridizations[node])
367
+ # a.SetNumExplicitHs(num_explicit_hss[node])
368
+ # idx = rdmol.AddAtom(a)
369
+ # node_to_idx[node] = idx
370
+ # bond_types = nx.get_edge_attributes(G, 'bond_type')
371
+ # for edge in G.edges():
372
+ # first, second = edge
373
+ # ifirst = node_to_idx[first]
374
+ # isecond = node_to_idx[second]
375
+ # bond_type = bond_types[first, second]
376
+ # rdmol.AddBond(ifirst, isecond, bond_type)
377
+ # Chem.SanitizeMol(rdmol)
378
+ # return rdmol
File without changes