MASSA-Algorithm 0.9.3__py3-none-any.whl → 0.9.5__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.
@@ -1,7 +1,8 @@
1
1
  import pandas as pd
2
2
  from rdkit.Chem import Descriptors
3
- from rdkit.Chem import rdMolDescriptors
4
- from rdkit.DataStructs import cDataStructs
3
+ from rdkit.Chem import AllChem
4
+ # from rdkit.Chem import rdMolDescriptors
5
+ # from rdkit.DataStructs import cDataStructs
5
6
 
6
7
  def physicochemical_descriptors(file):
7
8
  NumHAcceptors = {}
@@ -33,9 +34,25 @@ def physicochemical_descriptors(file):
33
34
  def atompairs_fingerprint(file):
34
35
  FP_dict = {}
35
36
  for i in file['molecules']:
36
- FPasBitVect = rdMolDescriptors.GetHashedAtomPairFingerprintAsBitVect(i, nBits=1024) # Determine the fingerprint of the molecule using AtomPairs Fingerprint.
37
- FPasBinary = cDataStructs.BitVectToText(FPasBitVect) # Convert fingerprint to text.
38
- BinaryAsList = list(FPasBinary) # Each bit of fingerprint will be a string item of a list.
37
+ # Updated AtomPair Fingerprint (without count).
38
+ # To use AtomPairCount use the function (fpgen.GetCountFingerprintAsNumPy).
39
+ # 1) Determine the fingerprint generator using AtomPairs Fingerprint.
40
+ # 2) Generate the numpy array fingerprint using the generator.
41
+ # 3) Transform the np.array in list.
42
+ fpgen = AllChem.GetAtomPairGenerator(fpSize=1024) # 1
43
+ FPasBinary = fpgen.GetFingerprintAsNumPy(i) # 2
44
+ BinaryAsList = list(FPasBinary) # 3
45
+
46
+ # DEPRECATED (by RDKit):
47
+ # 1) Determine the fingerprint of the molecule using AtomPairs Fingerprint.
48
+ # 2) Convert fingerprint to text.
49
+ # 3) Each bit of fingerprint will be a string item of a list.
50
+ # FPasBitVect = rdMolDescriptors.GetHashedAtomPairFingerprintAsBitVect(
51
+ # i, nBits=1024
52
+ # ) # 1
53
+ # FPasBinary = cDataStructs.BitVectToText(FPasBitVect) # 2
54
+ # BinaryAsList = list(FPasBinary) # 3
55
+
39
56
  BinaryAsNewList = []
40
57
  for a in BinaryAsList:
41
58
  b = int(a) # Each bit of fingerprint will be a int item of a list.
@@ -20,7 +20,7 @@ def initial_print():
20
20
  ██░░░▓▓▓▓░░░░░░░▓▓▓▓░░░░░░░▓▓▓▓░░░░█
21
21
  ██░░░░▓▓▓▓▓▓░░░░░▓▓▓▓▓▓░░░░░▓▓▓▓▓▓░░░░█ MASSA Algorithm:
22
22
  ████░░░░░▓▓▓▓░░░░░░░▓▓▓▓░░░░░░░▓▓▓▓░░░░░█████ Molecular data set sampling — Training-Test Separation
23
- █▓▓▓███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███▓▓▓█ Version: v. 0.9.3
23
+ █▓▓▓███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███▓▓▓█ Version: v. 0.9.5
24
24
  █▒▓▓▒▒▒████░░░░░░░░░░░░░░░░░░░░░░░░░░░░████▒▒▓▓▒█
25
25
  ██▓▒▒▒▓▓▓▓██████████████████████████████▓▓▓▒▒▒▒▓█ Developed by: Gabriel Corrêa Veríssimo
26
26
  ██▒▒▒▓▓▒▒▒▒▓▓▒▒▒▒▓▓▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▓▓▒▒▒▓▓▒▒██ LICENSE: AGPL-3.0
@@ -1,45 +1,294 @@
1
+ import pandas as pd
1
2
  from rdkit.Chem import AllChem
2
3
 
4
+
5
+ def find_smiles_column(columns):
6
+ """
7
+ Find the name of the "SMILES" column.
8
+
9
+ Args:
10
+ columns (list): receives a list with the name of pandas columns.
11
+
12
+ Raises:
13
+ ValueError: if there is no column named "SMILES" raises an error.
14
+
15
+ Returns:
16
+ column_name (str): returns the name of the "SMILES" column.
17
+ """
18
+ smiles_columns = []
19
+ smile_column = ""
20
+
21
+ for column in columns:
22
+ if "smiles" == column.lower():
23
+ smiles_columns.append(column)
24
+ if len(smiles_columns) > 1:
25
+ """
26
+ Warning: If there are more than one "SMILES" (case insensitive) column
27
+ the first one will be chosen.
28
+ """
29
+
30
+ print("Warning: There is more than one"
31
+ " column named 'smiles' (case insensitive)."
32
+ " The first one was chosen.")
33
+ smile_column = smiles_columns[0]
34
+ return smile_column
35
+ elif len(smiles_columns) == 1:
36
+ smile_column = smiles_columns[0]
37
+ return smile_column
38
+ else:
39
+ error = "Error: There is no column named 'SMILES'"
40
+ raise ValueError(error)
41
+
42
+
43
+ def find_name_column(columns):
44
+ """
45
+ Find the name of the molecule name column.
46
+
47
+ Args:
48
+ columns (list): receives a list with the name of pandas columns.
49
+
50
+ Returns:
51
+ column_name (str): returns the name of the molecule name column.
52
+ """
53
+
54
+ for column in columns:
55
+ if "molecule name" == column.lower():
56
+ print((f"Found '{column}' column."
57
+ " Using it to name the molecules."))
58
+ name_column = column
59
+ return name_column
60
+ elif "name" == column.lower():
61
+ print((f"Found '{column}' column."
62
+ " Using it to name the molecules."))
63
+ name_column = column
64
+ return name_column
65
+ elif "molecule chembl id" == column.lower():
66
+ print((f"Found '{column}' column."
67
+ " Using it to name the molecules."))
68
+ name_column = column
69
+ return name_column
70
+ elif "id" == column.lower():
71
+ print((f"Found '{column}' column."
72
+ " Using it to name the molecules."))
73
+ name_column = column
74
+ return name_column
75
+ else:
76
+ print(("Unable to find a column with molecule names."
77
+ " Using the index to name the molecules."))
78
+ name_column = "index"
79
+ return name_column
80
+
81
+
82
+ def read_df_smiles(df, WriteLog):
83
+ """Reads an dataframe and returns a sanitized molecule supplier.
84
+
85
+ Args:
86
+ df_supplier (pd.DataFrame): pd.DataFrame object with SMILES.
87
+ WriteLog (file object): Log file object to write error messages.
88
+
89
+ Returns:
90
+ AllChem.SDMolSupplier like: Sanitized molecule supplier.
91
+ """
92
+ columns = list(df.columns)
93
+
94
+ smi_name_column = find_smiles_column(columns)
95
+ name_name_column = find_name_column(columns)
96
+
97
+ # name_name_column = "index"
98
+ columns.remove(smi_name_column)
99
+ columns.remove(name_name_column)
100
+
101
+ mols = []
102
+ for index, row in df.iterrows():
103
+ try:
104
+ mol = AllChem.MolFromSmiles(row[smi_name_column])
105
+ AllChem.rdmolops.SanitizeMol(mol)
106
+ if name_name_column == "index":
107
+ mol.SetProp("_Name", str(index))
108
+ else:
109
+ mol.SetProp("_Name", str(row[name_name_column]))
110
+ for c in columns:
111
+ mol.SetProp(c, str(row[c]))
112
+ mols.append(mol)
113
+ except Exception as e:
114
+ mols.append(None)
115
+ mol_of_error = str(mol.GetProp('_Name'))
116
+ error = str(e)
117
+ precomposed = (f"[Error while reading molecule: {error}. "
118
+ f"Molecule name: {mol_of_error}].")
119
+ composed = precomposed+'\n'
120
+ print(precomposed)
121
+ WriteLog.write(composed)
122
+ if None in mols:
123
+ print("ERROR: Error while reading molecules. "
124
+ "Check the log.txt file for more information."
125
+ "\nERROR: Closing...")
126
+ exit()
127
+ return mols
128
+
129
+
130
+ def read_EXCEL_smiles(file, WriteLog):
131
+ df_supplier = pd.read_excel(file)
132
+ mols_sanitized = read_df_smiles(df_supplier, WriteLog)
133
+ return mols_sanitized
134
+
135
+
136
+ def read_CSV_smiles(file, WriteLog):
137
+ df_supplier = pd.read_csv(file, sep=",")
138
+ mols_sanitized = read_df_smiles(df_supplier)
139
+ return mols_sanitized
140
+
141
+
142
+ def read_SDF(file, WriteLog):
143
+ """Reads an SDF file and returns a sanitized molecule supplier.
144
+
145
+ Args:
146
+ file (str): Path to the SDF file.
147
+ WriteLog (file object): Log file object to write error messages.
148
+
149
+ Returns:
150
+ AllChem.SDMolSupplier: Sanitized molecule supplier.
151
+ """
152
+ # Open the input file.
153
+ mols_supplier = AllChem.SDMolSupplier(file, sanitize=False)
154
+ mols = []
155
+ for mol in mols_supplier:
156
+ try:
157
+ mols.append(AllChem.rdmolops.SanitizeMol(mol))
158
+ except Exception as e:
159
+ mols.append(None)
160
+ mol_of_error = str(mol.GetProp('_Name'))
161
+ error = str(e)
162
+ precomposed = (f"[Error while reading molecule: {error}. "
163
+ f"Molecule name: {mol_of_error}].")
164
+ composed = precomposed+'\n'
165
+ print(precomposed)
166
+ WriteLog.write(composed)
167
+ if None in mols:
168
+ print("ERROR: Error while reading molecules. "
169
+ "Check the log.txt file for more information."
170
+ "\nERROR: Closing...")
171
+ exit()
172
+ mols_sanitized = AllChem.SDMolSupplier(file, sanitize=True)
173
+ return mols_sanitized
174
+
175
+
176
+ def remove_comment_line(data):
177
+ # Remove lines starting with '#'
178
+ return '\n'.join(
179
+ line for line in data.splitlines() if not line.strip().startswith('#')
180
+ )
181
+
182
+
183
+ def mol2_properties(data):
184
+ data_split = data.split("@")
185
+ properties = {}
186
+ for d in data_split:
187
+ if "MOL_PROPERTY" in d:
188
+ list_values = d.split("\n")
189
+ p_name = list_values[1]
190
+ p_value = list_values[3]
191
+ properties[p_name] = p_value
192
+ return properties
193
+
194
+
195
+ def read_MOL2(file, WriteLog):
196
+ """Reads an MOL2 file from Discovery Studio
197
+ and returns a sanitized molecule supplier.
198
+
199
+ Args:
200
+ file (str): Path to the MOL2 file.
201
+ WriteLog (file object): Log file object to write error messages.
202
+
203
+ Returns:
204
+ AllChem.SDMolSupplier like: Sanitized molecule supplier.
205
+ """
206
+ with open(file, 'r') as f:
207
+ mol_data = f.read()
208
+ # Split the file contents on the delimiter
209
+ # Remove comment lines
210
+ mol_data = remove_comment_line(mol_data)
211
+
212
+ # Alert of MOL2 limitations.
213
+ print("""
214
+ ATTENTION: .mol2 file detected.
215
+ MOL2 files have limited support for storing molecular properties.
216
+ Therefore, the biological properties in this file may not be \
217
+ detected or even stored.
218
+ We do not recommend using a .mol2 file.
219
+ However, we provide support for .mol2 files generated by \
220
+ Discovery Studio Visualizer.
221
+ The biological properties in these files follow the format below:
222
+
223
+ @<SCITEGIC>MOL_PROPERTY
224
+ Name_of_property (e.g., pIC50 value)
225
+ Type_of_property (e.g., SciTegic.value.DoubleValue)
226
+ Value_of_the_property (e.g., 8.100000)
227
+ """)
228
+
229
+ # Split the file contents based on a delimiter for each molecule.
230
+ mol_blocks = mol_data.split("@<TRIPOS>MOLECULE")
231
+
232
+ # List to store molecules.
233
+ mols = []
234
+
235
+ # Iterate over each block and reassemble the molecule data
236
+ for mol_block in mol_blocks:
237
+ if mol_block.strip(): # To avoid empty blocks
238
+ mol_block = "@<TRIPOS>MOLECULE" + mol_block
239
+ properties = mol2_properties(mol_block)
240
+ mol = AllChem.MolFromMol2Block(mol_block)
241
+ try:
242
+ AllChem.rdmolops.SanitizeMol(mol)
243
+ for p, p_value in properties.items():
244
+ mol.SetProp(p, str(p_value))
245
+ mols.append(mol)
246
+ except Exception as e:
247
+ mols.append(None)
248
+ mol_of_error = str(mol.GetProp('_Name'))
249
+ error = str(e)
250
+ precomposed = (f"[Error while reading molecule: {error}. "
251
+ f"Molecule name: {mol_of_error}].")
252
+ composed = precomposed+'\n'
253
+ print(precomposed)
254
+ WriteLog.write(composed)
255
+ if None in mols:
256
+ print("ERROR: Error while reading molecules. "
257
+ "Check the log.txt file for more information."
258
+ "\nERROR: Closing...")
259
+ exit()
260
+ return mols
261
+
262
+
3
263
  def read_molecules(file, WriteLog):
4
- mols_supplier = AllChem.SDMolSupplier(file, sanitize=False) # Open the input file.
5
- mols = []
6
- for mol in mols_supplier:
7
- try:
8
- mols.append(AllChem.rdmolops.SanitizeMol(mol))
9
- except Exception as e:
10
- mols.append(None)
11
- mol_of_error = str(mol.GetProp('_Name'))
12
- error = str(e)
13
- precomposed = '[Error while reading molecule: \"' + error + '\". Molecule name: \"' + mol_of_error + '\".]'
14
- composed = precomposed+'\n'
15
- print(precomposed)
16
- WriteLog.write(composed)
17
- if None in mols:
18
- print('ERROR: Error while reading molecules. Check the log.txt file for more information. \nERROR: Closing...') # Print an error.
19
- exit()
20
- mols_supplier_sanitized = AllChem.SDMolSupplier(file, sanitize=True)
21
- return mols_supplier_sanitized
22
-
23
- def error_check(file):
24
- for i in file:
25
- if i == None: # If any molecule is not able to be read:
26
- print('ERROR: Unable to read a molecule') # Print an error.
27
- exit()
28
- else:
29
- pass
264
+ if file.endswith(".mol2"):
265
+ molecules = read_MOL2(file, WriteLog)
266
+ elif file.endswith(".sdf") or file.endswith(".mol"):
267
+ molecules = read_SDF(file, WriteLog)
268
+ elif file.endswith(".xlsx") or file.endswith(".xls"):
269
+ molecules = read_EXCEL_smiles(file, WriteLog)
270
+ elif file.endswith(".csv"):
271
+ molecules = read_CSV_smiles(file, WriteLog)
272
+ return molecules
273
+
30
274
 
31
275
  def hydrogen_add(file):
32
- molsH = []
33
- for i in file:
34
- molsH.append(AllChem.AddHs(i, addCoords = True)) # Add hydrogens keeping 3D coordenates.
35
- return molsH
36
-
37
- def get_sdf_property_names(file): # Extracting the property names from the ".sdf" input file.
38
- sdf_property_names = []
39
- for i in file:
40
- for a in list(i.GetPropNames()):
41
- sdf_property_names.append(a)
42
- sdf_property_names = list(set(sdf_property_names))
43
- if 'Name' in sdf_property_names: # Drop the molecule name from the property list.
44
- sdf_property_names.remove('Name')
45
- return sdf_property_names
276
+ molsH = []
277
+ for i in file:
278
+ i = AllChem.AddHs(i, addCoords=True)
279
+ molsH.append(i)
280
+ # Add hydrogens keeping 3D coordenates.
281
+ return molsH
282
+
283
+
284
+ def get_sdf_property_names(file):
285
+ # Extracting the property names from the ".sdf" input file.
286
+ sdf_property_names = []
287
+ for i in file:
288
+ for a in list(i.GetPropNames()):
289
+ sdf_property_names.append(a)
290
+ sdf_property_names = list(set(sdf_property_names))
291
+ if 'Name' in sdf_property_names:
292
+ # Drop the molecule name from the property list.
293
+ sdf_property_names.remove('Name')
294
+ return sdf_property_names
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MASSA-Algorithm
3
- Version: 0.9.3
3
+ Version: 0.9.5
4
4
  Summary: MASSA Algorithm is a Python package to separate data sets of molecules into training and test sets, considering the diversity of structural, physicochemical and biological characteristics of these molecules.
5
5
  Home-page: https://github.com/gcverissimo/MASSA_Algorithm
6
6
  Author: Gabriel Corrêa Veríssimo
@@ -18,13 +18,13 @@ Classifier: Topic :: Scientific/Engineering :: Chemistry
18
18
  Requires-Python: >=3.8
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: numpy <2.0
21
+ Requires-Dist: numpy<2.0
22
22
  Requires-Dist: rdkit
23
23
  Requires-Dist: pandas
24
- Requires-Dist: matplotlib >=3.2
25
- Requires-Dist: scipy >=1.6
26
- Requires-Dist: scikit-learn >0.24
27
- Requires-Dist: kmodes >=0.10
24
+ Requires-Dist: matplotlib>=3.2
25
+ Requires-Dist: scipy>=1.6
26
+ Requires-Dist: scikit-learn>0.24
27
+ Requires-Dist: kmodes>=0.10
28
28
 
29
29
  # MASSA Algorithm
30
30
  MASSA Algorithm: A tool for separating data sets of molecules into training and test sets. Developed with the objective of preparing data sets for the generation of prediction models in cheminformatics.
@@ -1,18 +1,18 @@
1
1
  MASSA_Algorithm/MASSA.py,sha256=PltTwmOsK-_q6MzmCxqY1AQMTXM-5XKB-3S6Yqe_VTo,9196
2
2
  MASSA_Algorithm/MASSAargs.py,sha256=MCOBlRm6sx6TUQHLwJrW-ktdSNiQltyFjyfJbS-1dVc,6777
3
3
  MASSA_Algorithm/MASSAcluster.py,sha256=orRK3rqEpH4j-C4LiS2rp3z4f1gM_rvsjgqiljvtlUI,11293
4
- MASSA_Algorithm/MASSAdescriptors.py,sha256=502A3NPxYMikXfSVsOz8u8p22hu5hgmZR5_4Am-8X5s,2141
4
+ MASSA_Algorithm/MASSAdescriptors.py,sha256=3wd4MXfqTJU6w-sUolEhsCKIOCS2ye1tSkXvOXwFn2c,2716
5
5
  MASSA_Algorithm/MASSAextraction.py,sha256=bADEWtpEE5P0hg9O-8piD659GrPfHUeqyyaAYCWlsAs,4976
6
- MASSA_Algorithm/MASSAlogos.py,sha256=h12kNzcQFWNMIZM-S7Pt3KaDquwmjkuNFSv0wQ-QaIE,3528
6
+ MASSA_Algorithm/MASSAlogos.py,sha256=CiSOgHodwBe8rNI2HbCWKkuQEr5MiwVc4tYIi-WuHO8,3528
7
7
  MASSA_Algorithm/MASSAmoloutput.py,sha256=LsyeCvIc9SPiFjVXTOQ3GVXDzhB9sc-MYWGGvIbOcwQ,2512
8
8
  MASSA_Algorithm/MASSAod.py,sha256=y0tizbYYtw34iJEf8c_5XPfQHHxF9RSRGjbmSZ0qRWk,487
9
- MASSA_Algorithm/MASSAopen_files.py,sha256=aPYCBNSmSPasL1wyuYvM7Nd1mTyGG9GMcyDdOAYQ3GE,1600
9
+ MASSA_Algorithm/MASSAopen_files.py,sha256=wQWBYB7zfKei7XOceS9kqZMj8xGA8AbfIDlBptyBOjE,9918
10
10
  MASSA_Algorithm/MASSApreparation.py,sha256=I4JpddMfBX1btYomNI5vflN1gyllJKodbQgtYf9imWY,3208
11
11
  MASSA_Algorithm/MASSAsplit.py,sha256=qsZgvXAat4UleaF0Qaa4Y-CtsMQU_NaIJvK-ypOzkbw,5330
12
12
  MASSA_Algorithm/__init__.py,sha256=yY3Tbs-t4HSl4I0Ev0RcHMnHU7SwljlWRveiRJkeCB8,10
13
- MASSA_Algorithm-0.9.3.dist-info/LICENSE,sha256=bx5iLIKjgAdYQ7sISn7DsfHRKkoCUm1154sJJKhgqnU,35184
14
- MASSA_Algorithm-0.9.3.dist-info/METADATA,sha256=IRbwh48vKeRgQGxbJn9iZLhovV8hPBocSzZ8anP2gO4,6542
15
- MASSA_Algorithm-0.9.3.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
16
- MASSA_Algorithm-0.9.3.dist-info/entry_points.txt,sha256=oMtqswy07Di-w2uIYAEvenBKl0ovsr9AYm_yxn6LGtU,63
17
- MASSA_Algorithm-0.9.3.dist-info/top_level.txt,sha256=IZyttJ20RSD8w9nAcaTHWAvkvxHV5FGaVGB7mDrw9Cc,16
18
- MASSA_Algorithm-0.9.3.dist-info/RECORD,,
13
+ MASSA_Algorithm-0.9.5.dist-info/LICENSE,sha256=bx5iLIKjgAdYQ7sISn7DsfHRKkoCUm1154sJJKhgqnU,35184
14
+ MASSA_Algorithm-0.9.5.dist-info/METADATA,sha256=pSx2OtrWq7RG_jLiXhFaBKoSDLuVenQtjVsLTfZUTnc,6537
15
+ MASSA_Algorithm-0.9.5.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
16
+ MASSA_Algorithm-0.9.5.dist-info/entry_points.txt,sha256=oMtqswy07Di-w2uIYAEvenBKl0ovsr9AYm_yxn6LGtU,63
17
+ MASSA_Algorithm-0.9.5.dist-info/top_level.txt,sha256=IZyttJ20RSD8w9nAcaTHWAvkvxHV5FGaVGB7mDrw9Cc,16
18
+ MASSA_Algorithm-0.9.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5