DrugDesign Data Analysis
Module of the DrugDesign project responsible for loading and pre-processing data from ChEMBL and PubChem
All Classes Namespaces Files Functions Variables Pages
functions Namespace Reference

Functions

pd.DataFrame AddedIC50andGI50ToCellLinesDF (pd.DataFrame data)
 
pd.DataFrame AddedIC50andKiToTargetsDF (pd.DataFrame data)
 
pd.DataFrame CleanedCellLineActivitiesDF (pd.DataFrame data, str cell_id, str activities_type)
 
pd.DataFrame CleanedTargetActivitiesDF (pd.DataFrame data, str target_id, str activities_type)
 
int CountCellLineActivitiesByFile (str file_name)
 
int CountTargetActivitiesByIC50 (str target_id)
 
int CountTargetActivitiesByKi (str target_id)
 
 DownloadCellLinesFromIdList ()
 
 DownloadCompoundsByMWRange (int less_limit, int greater_limit, str results_folder_name)
 
 DownloadCompoundToxicity (dict compound_data, str page_folder_name)
 
 DownloadTargetsFromIdList ()
 
pd.DataFrame ExpandedFromDictionariesCompoundsDF (pd.DataFrame data)
 
pd.DataFrame ExpandedFromDictionariesTargetsDF (pd.DataFrame data)
 
None FilterDownloadedToxicityByCharacteristics (str unit_type, str charact_1, str charact_2, str charact_3)
 
pd.DataFrame GetDataFrameFromUrl (str request_url, float sleep_time)
 
str GetLinkFromSid (int sid, str collection, int limit)
 
str GetMolfileFromCID (str cid, float|None sleep_time=config["PubChem_download_toxicity"]["sleep_time"])
 
list[str] GetMolfilesFromCIDs (list[str] cids, float|None sleep_time=config["PubChem_download_toxicity"]["sleep_time"])
 
 GetRawCellLinesData (str file_id, str output_path, bool print_to_console)
 
requests.Response GetResponse (str request_url, bool stream, float|None sleep_time=config["PubChem_download_toxicity"]["sleep_time"])
 
QuerySet QuerySetActivitiesByIC50 (str target_id)
 
QuerySet QuerySetActivitiesByKi (str target_id)
 
QuerySet QuerySetAllCellLines ()
 
QuerySet QuerySetAllTargets ()
 
QuerySet QuerySetCellLinesFromIdList (list[str] cell_line_chembl_id_list)
 
QuerySet QuerySetCompoundsByMWRange (int less_limit, int greater_limit)
 
QuerySet QuerySetTargetsFromIdList (list[str] target_chembl_id_list)
 
 SaveChEMBLMolfilesToSDFByIdList (list[str] molecule_chembl_id_list, str file_name, pd.DataFrame extra_data=pd.DataFrame())
 

Variables

Config filtering_config = toxicity_config["filtering"]
 
Config toxicity_config = config["PubChem_download_toxicity"]
 

Detailed Description

ChEMBL_download_activities/functions.py Этот модуль содержит функции для запроса и обработки данных об активностях (IC50, Ki) из базы данных ChEMBL, а также для очистки данных об активностях клеточных линий.
ChEMBL_download_cell_lines/functions.py Этот модуль содержит функции для загрузки и обработки данных о клеточных линиях из базы данных ChEMBL.
ChEMBL_download_compounds/functions.py Этот модуль содержит функции для запроса соединений из базы данных ChEMBL по диапазону молекулярной массы, преобразования данных в DataFrame и сохранения molfiles в SDF формат.
ChEMBL_download_targets/functions.py Этот модуль содержит функции для загрузки данных о целевых белках (targets) из базы данных ChEMBL, расширения словарей в DataFrame, добавления информации об активностях и сохранения результатов в CSV-файл.
PubChem_download_toxicity/functions.py Этот модуль содержит функции для скачивания данных о токсичности соединений из PubChem, их фильтрации, преобразования и сохранения в CSV и SDF файлы.

Function Documentation

◆ AddedIC50andGI50ToCellLinesDF()

pd.DataFrame functions.AddedIC50andGI50ToCellLinesDF ( pd.DataFrame data)
Добавляет столбцы `IC50` и `GI50` в DataFrame с данными о клеточных линиях, подсчитывая количество соответствующих активностей из CSV-файлов, а также опционально скачивает новые активности. Args: data (pd.DataFrame): DataFrame с данными о клеточных линиях. Returns: pd.DataFrame: DataFrame с добавленными столбцами `IC50` и `GI50`, содержащими количество соответствующих активностей.
80 ) -> pd.DataFrame:
81 """
82 Добавляет столбцы `IC50` и `GI50` в DataFrame с данными о клеточных линиях,
83 подсчитывая количество соответствующих активностей из CSV-файлов,
84 а также опционально скачивает новые активности.
85
86 Args:
87 data (pd.DataFrame): DataFrame с данными о клеточных линиях.
88
89 Returns:
90 pd.DataFrame: DataFrame с добавленными столбцами `IC50` и `GI50`,
91 содержащими количество соответствующих активностей.
92 """
93
94 # получаем конфигурацию для клеточных линий.
95 cell_lines_config: Config = config["ChEMBL_download_cell_lines"]
96
97 v_logger.info("Adding 'IC50' and 'GI50' columns to pandas.DataFrame...",
98 LogMode.VERBOSELY)
99
100 # проверяем, пуста ли папка с необработанными данными.
101 if IsFolderEmpty(cell_lines_config["raw_csv_folder_name"]):
102 v_logger.info("Getting raw cell_lines from Google.Drive...",
103 LogMode.VERBOSELY)
104
105 GetRawCellLinesData(cell_lines_config["raw_csv_g_drive_id"],
106 cell_lines_config["raw_csv_folder_name"],
107 config["Utils"]["VerboseLogger"]["verbose_print"])
108
109 v_logger.success("Getting raw cell_lines from Google.Drive!",
110 LogMode.VERBOSELY)
111
112 # добавляем столбец 'IC50', подсчитывая активности по файлам.
113 data["IC50"] = data.apply(
114 lambda value: CountCellLineActivitiesByFile(
115 f"{cell_lines_config["raw_csv_folder_name"]}/"
116 f"{value["cell_chembl_id"]}_IC50_activities.csv"), axis=1)
117
118 # добавляем столбец 'GI50', подсчитывая активности по файлам.
119 data["GI50"] = data.apply(
120 lambda value: CountCellLineActivitiesByFile(
121 f"{cell_lines_config["raw_csv_folder_name"]}/"
122 f"{value["cell_chembl_id"]}_GI50_activities.csv"), axis=1)
123
124 v_logger.success("Adding 'IC50' and 'GI50' columns to pandas.DataFrame!",
125 LogMode.VERBOSELY)
126
127 # проверяем, нужно ли скачивать активности.
128 if cell_lines_config["download_activities"]:
129 GetCellLineChEMBLActivitiesFromCSV(data)
130
131 try:
132 # оставляем только строки, в которых есть IC50_new и Ki_new
133 data = data[(data['IC50_new'].notna()
134 ) & (
135 data['GI50_new'].notna())]
136
137 data = data.copy()
138
139 data["IC50_new"] = data["IC50_new"].astype(int)
140 data["GI50_new"] = data["GI50_new"].astype(int)
141
142 # это исключение может возникнуть, если колонки нет.
143 except KeyError as exception:
144 # новых activities не скачалось, т.е. значение пересчитывать не надо.
145 if not config["skip_downloaded"]:
146 raise exception
147
148 # это исключение может возникнуть, если какое-то значение оказалось невалидным.
149 except pd.errors.IntCastingNaNError:
150 v_logger.warning("Cannot convert non-finite values!")
151
152 return data
153
154
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddedIC50andKiToTargetsDF()

pd.DataFrame functions.AddedIC50andKiToTargetsDF ( pd.DataFrame data)
Добавляет столбцы 'IC50' и 'Ki' в DataFrame с данными о целевых белках (targets), подсчитывая количество соответствующих активностей из базы данных ChEMBL, а также опционально скачивает новые активности. Args: data (pd.DataFrame): DataFrame с данными о целевых белках. Returns: pd.DataFrame: DataFrame с добавленными столбцами 'IC50' и 'Ki', содержащими количество соответствующих активностей.
140def AddedIC50andKiToTargetsDF(data: pd.DataFrame) -> pd.DataFrame:
141 """
142 Добавляет столбцы 'IC50' и 'Ki' в DataFrame с данными о целевых белках
143 (targets), подсчитывая количество соответствующих активностей из базы данных
144 ChEMBL, а также опционально скачивает новые активности.
145
146 Args:
147 data (pd.DataFrame): DataFrame с данными о целевых белках.
148
149 Returns:
150 pd.DataFrame: DataFrame с добавленными столбцами 'IC50' и 'Ki',
151 содержащими количество соответствующих активностей.
152 """
153
154 # получаем конфигурацию для скачивания целей.
155 targets_config: Config = config["ChEMBL_download_targets"]
156
157 v_logger.info(
158 "Adding 'IC50' and 'Ki' columns to pandas.DataFrame...",
159 LogMode.VERBOSELY)
160
161 # добавляем столбец 'IC50', подсчитывая активности.
162 data["IC50"] = data["target_chembl_id"].apply(
163 CountTargetActivitiesByIC50)
164 # добавляем столбец 'Ki', подсчитывая активности.
165 data["Ki"] = data["target_chembl_id"].apply(
166 CountTargetActivitiesByKi)
167
168 v_logger.success(
169 "Adding 'IC50' and 'Ki' columns to pandas.DataFrame!",
170 LogMode.VERBOSELY)
171
172 # если нужно скачивать активности.
173 if targets_config["download_activities"]:
174 # скачиваем активности для целевых белков.
175 DownloadTargetChEMBLActivities(data)
176
177 try:
178 # оставляем только строки, в которых есть IC50_new и Ki_new
179 data = data[(data['IC50_new'].notna()
180 ) & (
181 data['Ki_new'].notna())]
182
183 # преобразуем типы столбцов.
184 data["IC50_new"] = data["IC50_new"].astype(int)
185 data["Ki_new"] = data["Ki_new"].astype(int)
186
187 # это исключение может возникнуть, если колонки нет.
188 except KeyError as exception:
189 # новых activities не скачалось, т.е. значение пересчитывать не надо.
190 if not config["skip_downloaded"]:
191 raise exception
192
193 # это исключение может возникнуть, если какое-то значение оказалось невалидным.
194 except pd.errors.IntCastingNaNError:
195 v_logger.warning("Cannot convert non-finite values!")
196
197 return data
198
199
200@ReTry(attempts_amount=1)
Here is the caller graph for this function:

◆ CleanedCellLineActivitiesDF()

pd.DataFrame functions.CleanedCellLineActivitiesDF ( pd.DataFrame data,
str cell_id,
str activities_type )
Очищает DataFrame с данными об активностях для указанной клеточной линии (cell_id) по IC50 и GI50. Функция выполняет следующие шаги: 1. Выбирает нужные столбцы из DataFrame. 2. Переименовывает столбцы, приводя их к нижнему регистру и заменяя пробелы на "_". 3. Фильтрует данные, оставляя только значения с отношениями, единицами, организмами и типами активности из файла с конфигурациями. 4. Преобразует столбец "standard_value" в числовой тип. 5. Удаляет значения "standard_value", превышающие 1000000000 (1e9). 6. Удаляет столбец "assay_organism" и "standard_type". 7. Переименовывает столбец "smiles" в "canonical_smiles". 8. Вычисляет медиану для дублирующихся значений "standard_value" по "molecule_chembl_id". 9. Переиндексирует столбцы DataFrame в логическом порядке. Args: data (pd.DataFrame): DataFrame с данными об активностях клеточных линий. cell_id (str): Идентификатор клеточной линии. activities_type (str): Тип активности ("IC50" или "GI50") (используется только для логирования). Returns: pd.DataFrame: Очищенный DataFrame с данными об активностях клеточной линии.
205 ) -> pd.DataFrame:
206 """
207 Очищает DataFrame с данными об активностях
208 для указанной клеточной линии (cell_id) по IC50 и GI50.
209
210 Функция выполняет следующие шаги:
211 1. Выбирает нужные столбцы из DataFrame.
212 2. Переименовывает столбцы,
213 приводя их к нижнему регистру и заменяя пробелы на "_".
214 3. Фильтрует данные, оставляя только значения с отношениями, единицами,
215 организмами и типами активности из файла с конфигурациями.
216 4. Преобразует столбец "standard_value" в числовой тип.
217 5. Удаляет значения "standard_value", превышающие 1000000000 (1e9).
218 6. Удаляет столбец "assay_organism" и "standard_type".
219 7. Переименовывает столбец "smiles" в "canonical_smiles".
220 8. Вычисляет медиану для дублирующихся значений "standard_value"
221 по "molecule_chembl_id".
222 9. Переиндексирует столбцы DataFrame в логическом порядке.
223
224 Args:
225 data (pd.DataFrame): DataFrame с данными об активностях клеточных линий.
226 cell_id (str): Идентификатор клеточной линии.
227 activities_type (str): Тип активности ("IC50" или "GI50")
228 (используется только для логирования).
229
230 Returns:
231 pd.DataFrame: Очищенный DataFrame с данными об активностях клеточной линии.
232 """
233
234 # конфигурация для фильтрации активностей (клеточных линий).
235 filtering_config: Config =\
236 config["ChEMBL_download_activities"]["filtering"]["cell_lines"]
237
238 v_logger.info(f"Start cleaning {activities_type} activities DataFrame from "
239 f"{cell_id}...", LogMode.VERBOSELY)
240 v_logger.info("Deleting useless columns...", LogMode.VERBOSELY)
241
242 data = data[["Molecule ChEMBL ID", "Smiles", "Document ChEMBL ID",
243 "Standard Type", "Standard Relation", "Standard Value",
244 "Standard Units", "Assay ChEMBL ID", "Assay Description",
245 "Assay Type", "Assay Variant Accession", "Assay Variant Mutation",
246 "Action Type", "Data Validity Comment", "BAO Format ID", "BAO Label",
247 "Assay Organism"]]
248
249 data.columns = [column_name.lower().replace(" ", "_")
250 for column_name in data.columns]
251
252 v_logger.success("Deleting useless columns!", LogMode.VERBOSELY)
253 v_logger.info("Deleting inappropriate elements...", LogMode.VERBOSELY)
254
255 data = data[data["standard_relation"].isin(filtering_config["standard_relation"])]
256 data = data[data["standard_units"].isin(filtering_config["standard_units"])]
257 data = data[data["assay_organism"].isin(filtering_config["assay_organism"])]
258 data = data[data["standard_type"].isin(filtering_config["standard_type"])]
259
260 data['standard_value'] = data['standard_value'].astype(float)
261 data = data[data['standard_value'] <= 1000000000]
262
263 data = data.drop(["assay_organism", "standard_type"], axis=1)
264
265 data = data.rename(columns={'smiles': "canonical_smiles"})
266
267 v_logger.success("Deleting inappropriate elements!", LogMode.VERBOSELY)
268 v_logger.info("Calculating median for 'standard value'...", LogMode.VERBOSELY)
269
270 data = MedianDedupedDF(data, "molecule_chembl_id", "standard_value")
271
272 v_logger.success("Calculating median for 'standard value'!", LogMode.VERBOSELY)
273 v_logger.info("Reindexing columns in logical order...", LogMode.VERBOSELY)
274
275 data = data.reindex(columns=["molecule_chembl_id",
276 "canonical_smiles", "document_chembl_id",
277 "standard_relation", "standard_value", "standard_units",
278 "assay_chembl_id", "assay_description", "assay_type",
279 "assay_variant_accession", "assay_variant_mutation",
280 "action_type", "data_validity_description",
281 "bao_format", "bao_label"])
282
283 v_logger.success("Reindexing columns in logical order!", LogMode.VERBOSELY)
284 v_logger.success(f"End cleaning activities DataFrame from {cell_id}!",
285 LogMode.VERBOSELY)
286 v_logger.info("-", LogMode.VERBOSELY)
287
288 return data

◆ CleanedTargetActivitiesDF()

pd.DataFrame functions.CleanedTargetActivitiesDF ( pd.DataFrame data,
str target_id,
str activities_type )
Очищает DataFrame с данными об активностях для указанной цели (target_id) по IC50 и Ki. Функция выполняет следующие шаги: 1. Удаляет неинформативные столбцы. 2. Фильтрует данные, оставляя только значения с отношением, единицами, организмами, типами активности и типами анализа из файла с конфигурациями. 3. Преобразует столбец "standard_value" в числовой тип. 4. Удаляет значения "standard_value", превышающие 1000000000 (1e9). 5. Заменяет значения "Not Determined" в столбце 'activity_comment' на None. 6. Удаляет столбцы "target_organism" и "standard_type". 7. Вычисляет медиану для дублирующихся значений "standard_value" по "molecule_chembl_id". 8. Переиндексирует столбцы DataFrame в логическом порядке. Args: data (pd.DataFrame): DataFrame с данными об активностях, полученными из ChEMBL. target_id (str): Идентификатор цели из базы ChEMBL. activities_type (str): Тип активности ("IC50" или "Ki") (используется только для логирования). Returns: pd.DataFrame: Очищенный DataFrame с данными об активностях.
114 ) -> pd.DataFrame:
115 """
116 Очищает DataFrame с данными об активностях
117 для указанной цели (target_id) по IC50 и Ki.
118
119 Функция выполняет следующие шаги:
120 1. Удаляет неинформативные столбцы.
121 2. Фильтрует данные, оставляя только значения с отношением, единицами,
122 организмами, типами активности и типами анализа из файла с конфигурациями.
123 3. Преобразует столбец "standard_value" в числовой тип.
124 4. Удаляет значения "standard_value", превышающие 1000000000 (1e9).
125 5. Заменяет значения "Not Determined" в столбце 'activity_comment' на None.
126 6. Удаляет столбцы "target_organism" и "standard_type".
127 7. Вычисляет медиану для дублирующихся значений "standard_value"
128 по "molecule_chembl_id".
129 8. Переиндексирует столбцы DataFrame в логическом порядке.
130
131 Args:
132 data (pd.DataFrame): DataFrame с данными об активностях, полученными из ChEMBL.
133 target_id (str): Идентификатор цели из базы ChEMBL.
134 activities_type (str): Тип активности ("IC50" или "Ki")
135 (используется только для логирования).
136
137 Returns:
138 pd.DataFrame: Очищенный DataFrame с данными об активностях.
139 """
140 # конфигурация для фильтрации активностей (мишеней).
141 filtering_config: Config = config["ChEMBL_download_activities"]["filtering"]["targets"]
142
143 v_logger.info(f"Start cleaning {activities_type} activities DataFrame from "
144 f"{target_id}...", LogMode.VERBOSELY)
145 v_logger.info("Deleting useless columns...", LogMode.VERBOSELY)
146
147 data = data.drop(["activity_id", "activity_properties",
148 "document_journal", "document_year",
149 "molecule_pref_name", "pchembl_value",
150 "potential_duplicate", "qudt_units",
151 "record_id", "src_id", "standard_flag",
152 "standard_text_value", "standard_upper_value",
153 "target_chembl_id", "target_pref_name",
154 "target_tax_id", "text_value", "toid",
155 "type", "units", "uo_units", "upper_value",
156 "value", "ligand_efficiency", "relation"], axis=1)
157
158 v_logger.success("Deleting useless columns!", LogMode.VERBOSELY)
159 v_logger.info("Deleting inappropriate elements...", LogMode.VERBOSELY)
160
161 data = data[data["standard_relation"].isin(filtering_config["standard_relation"])]
162 data = data[data["standard_units"].isin(filtering_config["standard_units"])]
163 data = data[data["target_organism"].isin(filtering_config["target_organism"])]
164 data = data[data["standard_type"].isin(filtering_config["standard_type"])]
165 data = data[data["assay_type"].isin(filtering_config["assay_type"])]
166
167 data["standard_value"] = data["standard_value"].astype(float)
168 # неправдоподобные значения
169 data = data[data["standard_value"] <= 1000000000]
170
171 data['activity_comment'] = data['activity_comment'].replace(
172 "Not Determined", None)
173
174 data = data.drop(["target_organism", "standard_type"], axis=1)
175
176 v_logger.success("Deleting inappropriate elements!", LogMode.VERBOSELY)
177 v_logger.info("Calculating median for 'standard value'...", LogMode.VERBOSELY)
178
179 data = MedianDedupedDF(data, "molecule_chembl_id", "standard_value")
180
181 v_logger.success("Calculating median for 'standard value'!", LogMode.VERBOSELY)
182 v_logger.info("Reindexing columns in logical order...", LogMode.VERBOSELY)
183
184 data = data.reindex(columns=["molecule_chembl_id", "parent_molecule_chembl_id",
185 "canonical_smiles", "document_chembl_id",
186 "standard_relation", "standard_value", "standard_units",
187 "assay_chembl_id", "assay_description", "assay_type",
188 "assay_variant_accession", "assay_variant_mutation",
189 "action_type", "activity_comment",
190 "data_validity_comment", "data_validity_description",
191 "bao_endpoint", "bao_format", "bao_label"])
192
193 v_logger.success("Reindexing columns in logical order!", LogMode.VERBOSELY)
194 v_logger.success(f"End cleaning activities DataFrame from {target_id}!",
195 LogMode.VERBOSELY)
196 v_logger.info("-", LogMode.VERBOSELY)
197
198 return data
199
200
201@ReTry(attempts_amount=1)

◆ CountCellLineActivitiesByFile()

int functions.CountCellLineActivitiesByFile ( str file_name)
Подсчитывает количество строк (активностей) в CSV-файле, содержащем данные о клеточных линиях. Args: file_name (str): Имя файла CSV, содержащего данные об активностях клеточных линий. Returns: int: Количество строк в файле (предположительно, количество активностей).
94def CountCellLineActivitiesByFile(file_name: str) -> int:
95 """
96 Подсчитывает количество строк (активностей) в CSV-файле,
97 содержащем данные о клеточных линиях.
98
99 Args:
100 file_name (str): Имя файла CSV,
101 содержащего данные об активностях клеточных линий.
102
103 Returns:
104 int: Количество строк в файле (предположительно, количество активностей).
105 """
106
107 return sum(1 for _ in open(file_name, "r"))
108
109
110@ReTry(attempts_amount=1)

◆ CountTargetActivitiesByIC50()

int functions.CountTargetActivitiesByIC50 ( str target_id)
Подсчитывает количество активностей для указанной цели (target_id) на основе IC50. Args: target_id (str): Идентификатор цели из базы ChEMBL. Returns: int: Количество активностей типа IC50 для указанной цели.
66def CountTargetActivitiesByIC50(target_id: str) -> int:
67 """
68 Подсчитывает количество активностей для указанной цели (target_id) на основе IC50.
69
70 Args:
71 target_id (str): Идентификатор цели из базы ChEMBL.
72
73 Returns:
74 int: Количество активностей типа IC50 для указанной цели.
75 """
76
77 return len(QuerySetActivitiesByIC50(target_id)) # type: ignore
78
79
Here is the call graph for this function:

◆ CountTargetActivitiesByKi()

int functions.CountTargetActivitiesByKi ( str target_id)
Подсчитывает количество активностей для указанной цели (target_id) на основе Ki. Args: target_id (str): Идентификатор цели из базы ChEMBL. Returns: int: Количество активностей типа Ki для указанной цели.
80def CountTargetActivitiesByKi(target_id: str) -> int:
81 """
82 Подсчитывает количество активностей для указанной цели (target_id) на основе Ki.
83
84 Args:
85 target_id (str): Идентификатор цели из базы ChEMBL.
86
87 Returns:
88 int: Количество активностей типа Ki для указанной цели.
89 """
90
91 return len(QuerySetActivitiesByKi(target_id)) # type: ignore
92
93
Here is the call graph for this function:

◆ DownloadCellLinesFromIdList()

functions.DownloadCellLinesFromIdList ( )
Скачивает данные о клеточных линиях из ChEMBL по списку идентификаторов, добавляет информацию об активностях IC50 и GI50, проводит первичный анализ и сохраняет результаты в CSV-файл.
155def DownloadCellLinesFromIdList():
156 """
157 Скачивает данные о клеточных линиях из ChEMBL по списку идентификаторов,
158 добавляет информацию об активностях IC50 и GI50, проводит первичный анализ
159 и сохраняет результаты в CSV-файл.
160 """
161
162 # получаем конфигурацию для клеточных линий.
163 cell_lines_config: Config = config["ChEMBL_download_cell_lines"]
164
165 v_logger.info("Downloading cell_lines...", LogMode.VERBOSELY)
166
167 # получаем клеточные линии по списку id.
168 cell_lines_with_ids: QuerySet = QuerySetCellLinesFromIdList(
169 cell_lines_config["id_list"])
170
171 # если список id пуст, получаем все клеточные линии.
172 if cell_lines_config["id_list"] == []:
173 cell_lines_with_ids = QuerySetAllCellLines()
174
175 v_logger.info(f"Amount: {len(cell_lines_with_ids)}") # type: ignore
176 v_logger.success("Downloading cell_lines!", LogMode.VERBOSELY)
177 v_logger.info("Collecting cell_lines to pandas.DataFrame...",
178 LogMode.VERBOSELY)
179
180 # добавляем информацию об активностях IC50 и GI50.
181 data_frame = AddedIC50andGI50ToCellLinesDF(
182 pd.DataFrame(cell_lines_with_ids)) # type: ignore
183
184 v_logger.UpdateFormat(cell_lines_config["logger_label"],
185 cell_lines_config["logger_color"])
186
187 v_logger.success("Collecting cell_lines to pandas.DataFrame!",
188 LogMode.VERBOSELY)
189 v_logger.info(
190 f"Collecting cell_lines to .csv file in "
191 f"'{cell_lines_config["results_folder_name"]}'...",
192 LogMode.VERBOSELY)
193
194 # формируем имя файла для сохранения.
195 file_name: str = f"{cell_lines_config["results_folder_name"]}/"\
196 f"{cell_lines_config["results_file_name"]}.csv"
197
198 # сохраняем DataFrame в CSV-файл.
199 data_frame.to_csv(file_name, sep=";", index=False)
200
201 v_logger.success(
202 f"Collecting cell_lines to .csv file in "
203 f"'{cell_lines_config["results_folder_name"]}'!",
204 LogMode.VERBOSELY)
Here is the call graph for this function:

◆ DownloadCompoundsByMWRange()

functions.DownloadCompoundsByMWRange ( int less_limit,
int greater_limit,
str results_folder_name )
Возвращает молекулы в диапазоне молекулярной массы [less_limit; greater_limit) из базы ChEMBL, сохраняя их в .csv файл. Args: less_limit (int): нижняя граница. greater_limit (int): верхняя граница. results_folder_name (str): имя папки для закачки.
252 results_folder_name: str):
253 """
254 Возвращает молекулы в диапазоне молекулярной массы [less_limit;
255 greater_limit) из базы ChEMBL, сохраняя их в .csv файл.
256
257 Args:
258 less_limit (int): нижняя граница.
259 greater_limit (int): верхняя граница.
260 results_folder_name (str): имя папки для закачки.
261 """
262
263 v_logger.info(
264 f"Downloading molecules with mw in range [{less_limit}, "
265 f"{greater_limit})...",
266 LogMode.VERBOSELY)
267
268 # получаем молекулы в заданном диапазоне молекулярной массы.
269 mols_in_mw_range: QuerySet = QuerySetCompoundsByMWRange(
270 less_limit, greater_limit)
271
272 v_logger.info(f"Amount: {len(mols_in_mw_range)}", # type: ignore
273 LogMode.VERBOSELY)
274 v_logger.success(
275 f"Downloading molecules with mw in range [{less_limit}, "
276 f"{greater_limit})!",
277 LogMode.VERBOSELY)
278
279 v_logger.info("Collecting molecules to pandas.DataFrame...",
280 LogMode.VERBOSELY)
281
282 # преобразуем данные в DataFrame.
283 data_frame = ExpandedFromDictionariesCompoundsDF(pd.DataFrame(
284 mols_in_mw_range)) # type: ignore
285
286 v_logger.success("Collecting molecules to pandas.DataFrame!",
287 LogMode.VERBOSELY)
288 v_logger.info(
289 f"Collecting molecules to .csv file in '{results_folder_name}'...",
290 LogMode.VERBOSELY)
291
292 # формируем имя файла для сохранения.
293 file_name: str = f"{results_folder_name}/range_"\
294 f"{less_limit}_{greater_limit}_mw_mols.csv"
295
296 # сохраняем DataFrame в .csv файл.
297 data_frame.to_csv(file_name, sep=";", index=False)
298
299 v_logger.success(
300 f"Collecting molecules to .csv file in '{results_folder_name}'!",
301 LogMode.VERBOSELY)
302
303
Here is the call graph for this function:

◆ DownloadCompoundToxicity()

functions.DownloadCompoundToxicity ( dict compound_data,
str page_folder_name )
Скачиваем данные о токсичности соединения по информации из JSON PubChem и сохраняем их в CSV-файл. Args: compound_data (dict): словарь с информацией о соединении из JSON PubChem. page_folder_name (str): путь к директории, в которой будет сохранен файл.
237 page_folder_name: str):
238 """
239 Скачиваем данные о токсичности соединения по информации из JSON PubChem
240 и сохраняем их в CSV-файл.
241
242 Args:
243 compound_data (dict): словарь с информацией о соединении из JSON PubChem.
244 page_folder_name (str): путь к директории, в которой будет сохранен файл.
245 """
246
247 cid: str = ""
248
249 try:
250 # пытаемся получить CID соединения.
251 cid = compound_data["LinkedRecords"]["CID"][0]
252
253 # если CID отсутствует.
254 except KeyError:
255 v_logger.warning(
256 f"No 'cid' for 'sid': {compound_data["LinkedRecords"]["SID"][0]}"
257 f", skip.")
258 v_logger.info("-", LogMode.VERBOSELY)
259
260 return
261 # не сохраняем те соединения, у которых нет cid,
262 # так как невозможно вычислить молекулярные вес
263
264 primary_sid: int | None
265 try:
266 # пытаемся получить SID соединения.
267 primary_sid = int(compound_data["LinkedRecords"]["SID"][0])
268
269 # если SID отсутствует.
270 except KeyError:
271 primary_sid = None
272
273 # получаем данные из таблицы.
274 raw_table: str = compound_data["Data"][0]["Value"]["ExternalTableName"]
275 table_info: dict = {}
276
277 # разбираем данные таблицы.
278 for row in raw_table.split("&"):
279 key, value = row.split("=")
280 table_info[key] = value
281
282 # проверяем тип запроса.
283 if table_info["query_type"] != "sid":
284 v_logger.LogException(ValueError("Unknown query type at page "
285 f"{page_folder_name}"))
286
287 # получаем SID из данных таблицы.
288 sid = int(table_info["query"])
289
290 # проверяем соответствие SID.
291 if primary_sid != sid:
292 v_logger.warning(f"Mismatch between 'primary_sid' ({primary_sid}) "
293 f"and 'sid' ({sid}).")
294
295 # формируем имя файла.
296 compound_name: str = f"compound_{sid}_toxicity"
297
298 # формируем пути к файлам для разных единиц измерения.
299 compound_file_kg = f"{page_folder_name.format(unit_type="kg")}/"\
300 f"{compound_name}"
301 compound_file_m3 = f"{page_folder_name.format(unit_type="m3")}/"\
302 f"{compound_name}"
303
304 # если файл уже существует и скачивание пропущено, пропускаем.
305 if os.path.exists(f"{compound_file_kg}.csv") or\
306 os.path.exists(f"{compound_file_m3}.csv") and\
307 config["skip_downloaded"]:
308 v_logger.info(f"{compound_name} is already downloaded, skip.",
309 LogMode.VERBOSELY)
310 v_logger.info("-", LogMode.VERBOSELY)
311
312 return
313
314 v_logger.info(f"Downloading {compound_name}...", LogMode.VERBOSELY)
315
316 # получаем данные о токсичности из PubChem.
317 acute_effects = GetDataFrameFromUrl(
318 GetLinkFromSid(sid=sid,
319 collection=table_info["collection"],
320 limit=toxicity_config["limit"]),
321 toxicity_config["sleep_time"]
322 )
323
324 @ReTry()
325 def GetMolecularWeightByCid(cid: str | int) -> str:
326 """
327 Получает молекулярный вес соединения из PubChem REST API, используя его CID.
328
329 Args:
330 cid (str | int): PubChem Compound Identifier (CID) соединения.
331
332 Returns:
333 str: молекулярный вес соединения в виде строки.
334 """
335
336 # получаем молекулярный вес соединения из PubChem.
337 return GetResponse(
338 "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/"
339 f"{cid}/property/MolecularWeight/txt",
340 True, None).text.strip()
341
342 def CalcMolecularWeight(df: pd.DataFrame,
343 id_column: str,
344 ) -> pd.DataFrame:
345 """
346 Вычисляет и добавляет столбец 'mw' (молекулярный вес) в pd.DataFrame.
347
348 Args:
349 df (pd.DataFrame): исходный pd.DataFrame.
350 id_column (str): название столбца, содержащего ID соединений.
351
352 Returns:
353 pd.DataFrame: модифицированный DataFrame с добавленным столбцом 'mw'.
354 """
355
356 # получаем уникальные идентификаторы соединений.
357 unique_ids = df[id_column].dropna().unique()
358
359 # если найден только один уникальный идентификатор.
360 if len(unique_ids) == 1:
361 # получаем молекулярный вес для этого идентификатора.
362 mw = GetMolecularWeightByCid(unique_ids[0])
363
364 # если молекулярный вес найден.
365 if mw is not None:
366 # добавляем столбец с молекулярным весом в DataFrame.
367 df["mw"] = mw
368
369 v_logger.info(f"Found 'mw' by '{id_column}'.",
370 LogMode.VERBOSELY)
371
372 # если молекулярный вес не найден.
373 else:
374 v_logger.warning(
375 "Could not retrieve molecular weight by "
376 f"'{id_column}' for {unique_ids[0]}.")
377
378 # если идентификаторы не найдены.
379 elif len(unique_ids) == 0:
380 v_logger.warning(f"No '{id_column}' found for {unique_ids[0]}.")
381
382 # если идентификаторов несколько.
383 else:
384 v_logger.warning(
385 f"Non-unique 'mw' by {id_column} for {unique_ids[0]}.")
386
387 # применяем функцию получения молекулярного веса к каждому id.
388 df["mw"] = df[id_column].apply(GetMolecularWeightByCid)
389
390 # если некоторые значения молекулярного веса не найдены.
391 if df["mw"].isnull().any():
392 v_logger.warning(
393 f"Some 'mw' could not be retrieved by {id_column}.")
394
395 return df
396
397 def ExtractDoseAndTime(df: pd.DataFrame,
398 valid_units: list[str]) -> pd.DataFrame:
399 """
400 Преобразует DataFrame с данными о дозировках, извлекая числовое
401 значение, единицу измерения и период времени.
402
403 Args:
404 df (pd.DataFrame): таблица с колонкой "dose", содержащей
405 информацию о дозировках.
406 valid_units (list[str]): список допустимых единиц измерения дозы.
407
408 Returns:
409 DataFrame с тремя новыми колонками: "numeric_dose", "dose_value",
410 "time_period".
411 """
412
413 def ExtractDose(dose_str: str,
414 mw: float
415 ) -> tuple[float | None, str | None, str | None]:
416 """
417 Извлекает дозу, единицу измерения и период времени из строки
418 дозировки.
419
420 Args:
421 dose_str (str): строка, содержащая информацию о дозировке.
422 mw (float): молекулярная масса соединения.
423
424 Returns:
425 tuple[float | None, str | None, str | None]: кортеж, содержащий:
426 - числовую дозу (float или None, если извлечь не удалось).
427 - единицу измерения дозы (str или None, если извлечь не удалось).
428 - период времени (str или None, если извлечь не удалось).
429 """
430
431 # если в строке нет пробелов, возвращаем None.
432 if " " not in dose_str:
433 return None, None, None
434
435 num_dose: float | str | None = None
436 dose_unit: str | None = None
437 time_per: str | None = None
438
439 try:
440 # если строка дозировки содержит не два элемента, возвращаем None.
441 if len(dose_str.split(" ")) != 2:
442 return None, None, None
443
444 # разделяем строку на количество дозы и единицы измерения.
445 dose_amount_str, dose_and_time = dose_str.split(" ")
446 # преобразуем количество дозы в число.
447 num_dose = float(dose_amount_str)
448
449 # если не удалось преобразовать количество дозы в число.
450 except ValueError:
451 v_logger.warning(f"Unsupported dose string: {dose_str}",
452 LogMode.VERBOSELY)
453 return None, None, None
454
455 # определяем, есть ли период времени.
456 match dose_str.count("/"):
457 case 1: # нету time period или это pp*/time
458 # если строка начинается с "p", это "pp*/time".
459 if dose_and_time.startswith("p"):
460 dose_unit, time_per = dose_and_time.split("/")
461 else:
462 dose_unit = dose_and_time
463 time_per = None
464
465 case 2: # есть time period
466 # извлекаем единицу измерения и период времени.
467 dose_unit = "/".join(dose_and_time.split("/")[:-1])
468 time_per = dose_and_time.split("/")[-1]
469
470 case _:
471 return None, None, None
472
473 # если единица измерения не поддерживается.
474 if dose_unit not in valid_units:
475 v_logger.warning(f"Unsupported dose_unit: {dose_unit}",
476 LogMode.VERBOSELY)
477 return None, None, None
478
479 unit_prefix: str = dose_unit
480 unit_suffix: str = "m3"
481
482 # если единица измерения содержит "/", разделяем ее.
483 if dose_unit.count("/") > 0:
484 unit_prefix, unit_suffix = dose_unit.split("/")
485
486 # если суффикс не поддерживается.
487 if unit_suffix not in ("kg", "m3"):
488 v_logger.warning(f"Unsupported dose_unit: {dose_unit}",
489 LogMode.VERBOSELY)
490 return None, None, None
491
492 unit_prefix = unit_prefix.lower()
493
494 # словарь с коэффициентами перевода единиц измерения.
495 conversions: dict[str, float] = {
496 "mg": 1,
497 "gm": 1000,
498 "g": 1000,
499 "ng": 0.000001,
500 "ug": 0.001,
501
502 "ml": 1000,
503 "nl": 0.001, # 1000 * 0.000001
504 "ul": 1, # 1000 * 0.001
505
506 "ppm": 24.45 / mw, # 1 ppm = 1 mg/m3 * 24.45/mw
507 "ppb": 0.001 * 24.45 / mw, # 1 ppb = 0.001 ppm
508 "pph": 1 / 60 * 24.45 / mw, # 1 pph = 1/60 ppm
509 }
510
511 # переводим известные единицы к "mg/kg" и "mg/m3".
512 if unit_prefix in conversions:
513 num_dose *= conversions[unit_prefix]
514 dose_unit = "mg/" + unit_suffix
515
516 # если префикс не поддерживается.
517 else:
518 v_logger.warning(f"Unsupported dose_unit: {dose_unit}",
519 LogMode.VERBOSELY)
520 return None, None, None
521
522 return num_dose, dose_unit, time_per
523
524 # применяем функцию извлечения дозы к каждой строке DataFrame.
525 df[["numeric_dose", "dose_units", "time_period"]] = df.apply(
526 lambda row: pd.Series(ExtractDose(row["dose"], row["mw"])),
527 axis=1)
528 # удаляем исходный столбец "dose" и переименовываем новый.
529 df = df.drop(columns=["dose"]).rename(
530 columns={"numeric_dose": "dose"})
531
532 return df
533
534 def SaveMolfileWithToxicityToSDF(df: pd.DataFrame, unit_type: str):
535 """
536 Сохраняет molfile соединения с данными о токсичности в SDF-файл.
537
538 Args:
539 df (pd.DataFrame): DataFrame, содержащий данные о токсичности соединения.
540 unit_type (str): тип единиц измерения (например, "kg" или "m3").
541 """
542
543 # создаем пустой DataFrame для хранения данных.
544 listed_df = pd.DataFrame()
545
546 # итерируемся по столбцам DataFrame.
547 for column_name in df.columns:
548 # получаем данные столбца в виде списка.
549 full_column_data = df[column_name].tolist()
550
551 # добавляем данные столбца в новый DataFrame.
552 listed_df[column_name] = [full_column_data]
553 # если элемент уникален.
554 if len(DedupedList(full_column_data)) == 1:
555 # то записываем только его.
556 listed_df.loc[0, column_name] = full_column_data[0]
557
558 # сохраняем molfile в SDF-файл.
559 SaveMolfilesToSDF(
560 data=pd.DataFrame({"cid": [cid],
561 "molfile": [GetMolfileFromCID(cid)]}),
562 file_name=(
563 f"{toxicity_config["molfiles_folder_name"]}/"
564 f"{compound_name}_{unit_type}"),
565 molecule_id_column_name="cid",
566 extra_data=listed_df,
567 indexing_lists=True)
568
569 def SaveToxicityUnitSpecification(compound_file_unit: str,
570 unit_str: str,
571 valid_units: list[str],
572 acute_effects: pd.DataFrame):
573 """
574 Фильтрует, преобразует и сохраняет данные о токсичности для указанного
575 типа единиц измерения.
576
577 Args:
578 compound_file_unit (str): имя файла для сохранения (без расширения).
579 unit_str (str): тип единиц измерения ("kg" или "m3").
580 valid_units (list[str]): список допустимых единиц измерения.
581 acute_effects (pd.DataFrame): DataFrame с данными о токсичности.
582 """
583
584 v_logger.info("Filtering 'organism' and 'route'...",
585 LogMode.VERBOSELY)
586
587 # фильтруем данные по организму.
588 acute_effects_unit = acute_effects[acute_effects["organism"].isin(
589 filtering_config[unit_str]["organism"])]
590 # фильтруем данные по способу введения.
591 acute_effects_unit = acute_effects_unit[
592 acute_effects_unit["route"].isin(
593 filtering_config[unit_str]["route"])]
594
595 v_logger.success("Filtering 'organism' and 'route'!",
596 LogMode.VERBOSELY)
597
598 v_logger.info(f"Filtering 'dose' in {unit_str}...",
599 LogMode.VERBOSELY)
600
601 # если DataFrame пустой, пропускаем.
602 if acute_effects_unit.empty:
603 v_logger.warning(
604 f"{compound_name}_{unit_str} is empty, no need saving, skip.",
605 LogMode.VERBOSELY)
606 return
607
608 # если столбец "dose" присутствует.
609 if "dose" in acute_effects_unit.columns:
610 # извлекаем дозу, единицы измерения и время.
611 acute_effects_unit = ExtractDoseAndTime(acute_effects_unit,
612 valid_units)
613
614 # преобразуем значения столбца "dose" в числовой формат.
615 acute_effects_unit["dose"] = pd.to_numeric(
616 acute_effects_unit["dose"], errors="coerce")
617
618 # если столбец "dose" отсутствует.
619 else:
620 v_logger.warning(f"No dose in {compound_name}_{unit_str}, skip.",
621 LogMode.VERBOSELY)
622 return
623
624 # если DataFrame пустой, пропускаем.
625 if acute_effects_unit.empty:
626 v_logger.warning(
627 f"{compound_name}_{unit_str} is empty, no need saving, skip.",
628 LogMode.VERBOSELY)
629 return
630
631 # если столбцы "dose" или "dose_units" отсутствуют.
632 if "dose" not in acute_effects_unit.columns or\
633 "dose_units" not in acute_effects_unit.columns:
634 v_logger.warning(
635 f"{compound_name}_{unit_str} misses 'dose' or 'dose_units'"
636 f", skip.",
637 LogMode.VERBOSELY)
638 return
639
640 v_logger.success(f"Filtering 'dose' in {unit_str}!",
641 LogMode.VERBOSELY)
642
643 v_logger.info(f"Adding 'pLD' to {compound_name}_{unit_str}...",
644 LogMode.VERBOSELY)
645
646 # вычисляем pLD.
647 acute_effects_unit["pLD"] = -np.log10(
648 (acute_effects_unit["dose"] / acute_effects_unit["mw"]) / 1000000)
649
650 v_logger.success(f"Adding 'pLD' to {compound_name}_{unit_str}!",
651 LogMode.VERBOSELY)
652
653 v_logger.info(f"Saving {compound_name}_{unit_str} to .csv...",
654 LogMode.VERBOSELY)
655
656 # заменяем пустые строки на NaN.
657 acute_effects_unit = acute_effects_unit.replace('', np.nan)
658 # удаляем столбцы, состоящие только из NaN.
659 acute_effects_unit = acute_effects_unit.dropna(axis=1, how='all')
660
661 # проверяем наличие дозы и единиц ее измерения.
662 if "dose" in acute_effects_unit.columns and\
663 "dose_units" in acute_effects_unit.columns:
664 # оставляем только строки, в которых есть информация о дозе и
665 # единицах измерения.
666 acute_effects_unit =\
667 acute_effects_unit[(acute_effects_unit['dose_units'].notna()
668 ) & (
669 acute_effects_unit['dose'].notna())]
670
671 # если нет нужных столбцов.
672 else:
673 v_logger.warning(
674 f"{compound_name}_{unit_str} misses 'dose' or 'dose_units'"
675 f", skip.",
676 LogMode.VERBOSELY)
677 return
678
679 # сохраняем DataFrame в CSV-файл.
680 acute_effects_unit.to_csv(f"{compound_file_unit}.csv",
681 sep=";",
682 index=False,
683 mode="w")
684
685 v_logger.success(f"Saving {compound_name}_{unit_str} to .csv!",
686 LogMode.VERBOSELY)
687
688 # если необходимо скачивать соединения в SDF.
689 if toxicity_config["download_compounds_sdf"]:
690 v_logger.info(f"Saving {compound_name}_{unit_str} to .sdf...",
691 LogMode.VERBOSELY)
692
693 # создаем директорию для SDF-файлов.
694 os.makedirs(toxicity_config["molfiles_folder_name"],
695 exist_ok=True)
696
697 # сохраняем molfile в SDF-файл.
698 SaveMolfileWithToxicityToSDF(acute_effects_unit, unit_str)
699
700 v_logger.success(f"Saving {compound_name}_{unit_str} to .sdf!",
701 LogMode.VERBOSELY)
702
703 v_logger.info("Adding 'mw'...", LogMode.VERBOSELY)
704
705 # добавляем столбец с молекулярным весом.
706 acute_effects = CalcMolecularWeight(acute_effects, "cid")
707
708 try:
709 # преобразуем значения столбца "mw" в числовой формат.
710 acute_effects["mw"] = pd.to_numeric(acute_effects["mw"],
711 errors="coerce")
712
713 v_logger.success("Adding 'mw'!", LogMode.VERBOSELY)
714
715 # если столбец "mw" не найден.
716 except KeyError:
717 v_logger.warning(f"No 'mw' for {compound_name}, skip.")
718 return
719
720 v_logger.info("~", LogMode.VERBOSELY)
721
722 # сохраняем данные о токсичности для единиц измерения "kg".
723 SaveToxicityUnitSpecification(compound_file_unit=compound_file_kg,
724 unit_str="kg",
725 valid_units=["gm/kg",
726 "g/kg",
727
728 "mg/kg",
729 "ug/kg",
730 "ng/kg",
731
732 "mL/kg",
733 "uL/kg",
734 "nL/kg"],
735 acute_effects=acute_effects)
736
737 v_logger.info("·", LogMode.VERBOSELY)
738
739 # сохраняем данные о токсичности для единиц измерения "m3".
740 SaveToxicityUnitSpecification(compound_file_unit=compound_file_m3,
741 unit_str="m3",
742 valid_units=["gm/m3",
743 "g/m3",
744
745 "mg/m3",
746 "ug/m3",
747 "ng/m3",
748
749 "mL/m3",
750 "uL/m3",
751 "nL/m3",
752
753 "ppm",
754 "ppb",
755 "pph"],
756 acute_effects=acute_effects)
757
758 v_logger.info("·", LogMode.VERBOSELY)
759 v_logger.success(f"Downloading {compound_name}!", LogMode.VERBOSELY)
760 v_logger.info("-", LogMode.VERBOSELY)
761
762
763# MARK: FilterDownloadedToxicityByCharacteristics
764
765
Here is the call graph for this function:

◆ DownloadTargetsFromIdList()

functions.DownloadTargetsFromIdList ( )
Скачивает данные о целевых белках (targets) из ChEMBL по списку идентификаторов, добавляет информацию об активностях IC50 и Ki, проводит первичный анализ и сохраняет результаты в CSV-файл.
201def DownloadTargetsFromIdList():
202 """
203 Скачивает данные о целевых белках (targets) из ChEMBL по списку
204 идентификаторов, добавляет информацию об активностях IC50 и Ki, проводит
205 первичный анализ и сохраняет результаты в CSV-файл.
206 """
207
208 # получаем конфигурацию для скачивания целей.
209 targets_config: Config = config["ChEMBL_download_targets"]
210
211 v_logger.info("Downloading targets...", LogMode.VERBOSELY)
212
213 # получаем цели по списку id.
214 targets_with_ids: QuerySet = QuerySetTargetsFromIdList(
215 targets_config["id_list"])
216
217 # если список id пуст, получаем все цели.
218 if targets_config["id_list"] == []:
219 targets_with_ids = QuerySetAllTargets()
220
221 v_logger.info(f"Amount: {len(targets_with_ids)}") # type: ignore
222 v_logger.success("Downloading targets!", LogMode.VERBOSELY)
223 v_logger.info("Collecting targets to pandas.DataFrame..",
224 LogMode.VERBOSELY)
225
226 # добавляем информацию об активностях IC50 и Ki.
227 data_frame = AddedIC50andKiToTargetsDF(
228 ExpandedFromDictionariesTargetsDF(
229 pd.DataFrame(targets_with_ids) # type: ignore
230 ))
231
232 v_logger.UpdateFormat(targets_config["logger_label"],
233 targets_config["logger_color"])
234
235 v_logger.success("Collecting targets to pandas.DataFrame!",
236 LogMode.VERBOSELY)
237 v_logger.info(
238 f"Collecting targets to .csv file in "
239 f"'{targets_config["results_folder_name"]}'...",
240 LogMode.VERBOSELY)
241
242 # формируем имя файла.
243 file_name: str = f"{targets_config["results_folder_name"]}/"\
244 f"{targets_config["results_file_name"]}.csv"
245
246 # сохраняем DataFrame в CSV-файл.
247 data_frame.to_csv(file_name, sep=";", index=False)
248
249 v_logger.success(
250 f"Collecting targets to .csv file in "
251 f"'{targets_config["results_folder_name"]}'!",
252 LogMode.VERBOSELY)
Here is the call graph for this function:

◆ ExpandedFromDictionariesCompoundsDF()

pd.DataFrame functions.ExpandedFromDictionariesCompoundsDF ( pd.DataFrame data)
Избавляет pd.DataFrame от словарей и списков словарей в столбцах, разбивая их на подстолбцы. Args: data (pd.DataFrame): исходный pd.DataFrame. Returns: pd.DataFrame: "раскрытый" pd.DataFrame.
52def ExpandedFromDictionariesCompoundsDF(data: pd.DataFrame) -> pd.DataFrame:
53 """
54 Избавляет pd.DataFrame от словарей и списков словарей в столбцах, разбивая
55 их на подстолбцы.
56
57 Args:
58 data (pd.DataFrame): исходный pd.DataFrame.
59
60 Returns:
61 pd.DataFrame: "раскрытый" pd.DataFrame.
62 """
63
64 def ExtractedValuesFromColumn(df: pd.DataFrame,
65 column_name: str,
66 key: str,
67 is_list: bool = True
68 ) -> pd.Series:
69 """
70 Извлекает значения из указанного столбца DataFrame на основе заданного
71 ключа.
72
73 Args:
74 df (pd.DataFrame): DataFrame, из которого нужно извлечь значения.
75 column_name (str): название столбца, из которого нужно извлечь
76 значения.
77 key (str): ключ, по которому нужно извлечь значения из словарей.
78 is_list (bool, optional): флаг, указывающий, является ли значение
79 в столбце списком словарей.
80
81 Returns:
82 pd.Series: Series, содержащий извлеченные значения.
83 """
84
85 # если значение в столбце - список словарей.
86 if is_list:
87 return df[column_name].apply(
88 lambda x: [d[key] for d in x] if x else [])
89
90 # если значение в столбце - не список словарей.
91 return [item[key] if isinstance(item, dict) else None for item in
92 df[column_name]] # type: ignore
93
94 # извлекаем значения из различных столбцов DataFrame.
95 exposed_data = pd.DataFrame({
96 # ! cross_references
97 "xref_id": ExtractedValuesFromColumn(data,
98 "cross_references",
99 "xref_id"),
100 "xref_name": ExtractedValuesFromColumn(data,
101 "cross_references",
102 "xref_name"),
103 "xref_src": ExtractedValuesFromColumn(data,
104 "cross_references",
105 "xref_src"),
106 # ! molecule_hierarchy
107 "active_chembl_id": ExtractedValuesFromColumn(data,
108 "molecule_hierarchy",
109 "active_chembl_id",
110 is_list=False),
111 "molecule_chembl_id": ExtractedValuesFromColumn(data,
112 "molecule_hierarchy",
113 "molecule_chembl_id",
114 is_list=False),
115 "parent_chembl_id": ExtractedValuesFromColumn(data,
116 "molecule_hierarchy",
117 "parent_chembl_id",
118 is_list=False),
119 # ! molecule_properties
120 "alogp": ExtractedValuesFromColumn(data,
121 "molecule_properties",
122 "alogp",
123 is_list=False),
124 "aromatic_rings": ExtractedValuesFromColumn(data,
125 "molecule_properties",
126 "aromatic_rings",
127 is_list=False),
128 "cx_logd": ExtractedValuesFromColumn(data,
129 "molecule_properties",
130 "cx_logd",
131 is_list=False),
132 "cx_logp": ExtractedValuesFromColumn(data,
133 "molecule_properties",
134 "cx_logp",
135 is_list=False),
136 "cx_most_apka": ExtractedValuesFromColumn(data,
137 "molecule_properties",
138 "cx_most_apka",
139 is_list=False),
140 "cx_most_bpka": ExtractedValuesFromColumn(data,
141 "molecule_properties",
142 "cx_most_bpka",
143 is_list=False),
144 "full_molformula": ExtractedValuesFromColumn(data,
145 "molecule_properties",
146 "full_molformula",
147 is_list=False),
148 "full_mwt": ExtractedValuesFromColumn(data,
149 "molecule_properties",
150 "full_mwt",
151 is_list=False),
152 "hba": ExtractedValuesFromColumn(data,
153 "molecule_properties",
154 "hba", is_list=False),
155 "hba_lipinski": ExtractedValuesFromColumn(data,
156 "molecule_properties",
157 "hba_lipinski",
158 is_list=False),
159 "hbd": ExtractedValuesFromColumn(data,
160 "molecule_properties",
161 "hbd", is_list=False),
162 "hbd_lipinski": ExtractedValuesFromColumn(data,
163 "molecule_properties",
164 "hbd_lipinski",
165 is_list=False),
166 "heavy_atoms": ExtractedValuesFromColumn(data,
167 "molecule_properties",
168 "heavy_atoms",
169 is_list=False),
170 "molecular_species": ExtractedValuesFromColumn(data,
171 "molecule_properties",
172 "molecular_species",
173 is_list=False),
174 "mw_freebase": ExtractedValuesFromColumn(data,
175 "molecule_properties",
176 "mw_freebase",
177 is_list=False),
178 "mw_monoisotopic": ExtractedValuesFromColumn(data,
179 "molecule_properties",
180 "mw_monoisotopic",
181 is_list=False),
182 "np_likeness_score": ExtractedValuesFromColumn(data,
183 "molecule_properties",
184 "np_likeness_score",
185 is_list=False),
186 "num_lipinski_ro5_violations": ExtractedValuesFromColumn(data,
187 "molecule_properties",
188 "num_lipinski_"
189 "ro5_violations",
190 is_list=False),
191 "num_ro5_violations": ExtractedValuesFromColumn(data,
192 "molecule_properties",
193 "num_ro5_violations",
194 is_list=False),
195 "psa": ExtractedValuesFromColumn(data,
196 "molecule_properties",
197 "psa",
198 is_list=False),
199 "qed_weighted": ExtractedValuesFromColumn(data,
200 "molecule_properties",
201 "qed_weighted",
202 is_list=False),
203 "ro3_pass": ExtractedValuesFromColumn(data,
204 "molecule_properties",
205 "ro3_pass",
206 is_list=False),
207 "rtb": ExtractedValuesFromColumn(data,
208 "molecule_properties",
209 "rtb",
210 is_list=False),
211 # ! molecule_structures
212 "canonical_smiles": ExtractedValuesFromColumn(data,
213 "molecule_structures",
214 "canonical_smiles",
215 is_list=False),
216 "molfile": ExtractedValuesFromColumn(data,
217 "molecule_structures",
218 "molfile",
219 is_list=False),
220 "standard_inchi": ExtractedValuesFromColumn(data,
221 "molecule_structures",
222 "standard_inchi",
223 is_list=False),
224 "standard_inchi_key": ExtractedValuesFromColumn(data,
225 "molecule_structures",
226 "standard_inchi_key",
227 is_list=False),
228 # ! molecule_synonyms
229 "molecule_synonym": ExtractedValuesFromColumn(data,
230 "molecule_synonyms",
231 "molecule_synonym"),
232 "syn_type": ExtractedValuesFromColumn(data,
233 "molecule_synonyms",
234 "syn_type"),
235 "synonyms": ExtractedValuesFromColumn(data,
236 "molecule_synonyms",
237 "synonyms"),
238 })
239
240 # удаляем исходные столбцы со словарями и списками словарей.
241 data = data.drop(["cross_references", "molecule_hierarchy",
242 "molecule_properties", "molecule_structures",
243 "molecule_synonyms"], axis=1)
244
245 # объединяем исходный DataFrame с извлеченными значениями.
246 return pd.concat([data, exposed_data], axis=1)
247
248
249@ReTry(attempts_amount=1)
Here is the caller graph for this function:

◆ ExpandedFromDictionariesTargetsDF()

pd.DataFrame functions.ExpandedFromDictionariesTargetsDF ( pd.DataFrame data)
Избавляет pd.DataFrame от словарей и списков словарей в столбцах, разбивая их на подстолбцы. Args: data (pd.DataFrame): исходный pd.DataFrame. Returns: pd.DataFrame: "раскрытый" pd.DataFrame.
53def ExpandedFromDictionariesTargetsDF(data: pd.DataFrame) -> pd.DataFrame:
54 """
55 Избавляет pd.DataFrame от словарей и списков словарей в столбцах, разбивая
56 их на подстолбцы.
57
58 Args:
59 data (pd.DataFrame): исходный pd.DataFrame.
60
61 Returns:
62 pd.DataFrame: "раскрытый" pd.DataFrame.
63 """
64
65 def ExtractedValuesFromColumn(df: pd.DataFrame,
66 column_name: str,
67 key: str) -> pd.Series:
68 """
69 Извлекает значения из указанного столбца DataFrame, который содержит
70 списки словарей, на основе заданного ключа.
71
72 Args:
73 df (pd.DataFrame): DataFrame, из которого нужно извлечь значения.
74 column_name (str): название столбца, содержащего списки словарей.
75 key (str): ключ, по которому нужно извлечь значения из словарей.
76
77 Returns:
78 pd.Series: Series, содержащий списки извлеченных значений.
79 """
80
81 # извлекаем значения из указанного столбца DataFrame.
82 return df[column_name].apply(
83 lambda x: [d[key] for d in x] if x else [])
84
85 # извлекаем значения из столбца cross_references.
86 exposed_data = pd.DataFrame({
87 "xref_id": ExtractedValuesFromColumn(data, "cross_references", "xref_id"),
88 "xref_name": ExtractedValuesFromColumn(data, "cross_references", "xref_name"),
89 "xref_src": ExtractedValuesFromColumn(data, "cross_references", "xref_src"),
90 })
91
92 # избавляемся от списков, так как в них находятся одиночные словари.
93 data["target_components"] = data["target_components"].apply(
94 lambda x: x[0] if x else {"accession": None,
95 "component_description": None,
96 "component_id": None,
97 "component_type": None,
98 "relationship": None,
99 "target_component_synonyms": [],
100 "target_component_xrefs": []})
101
102 # создаем DataFrame из столбца target_components.
103 target_components_data = pd.DataFrame(
104 data["target_components"].values.tolist())
105
106 # извлекаем значения из столбца target_component_synonyms и
107 # target_component_xrefs.
108 exposed_target_components_data = pd.DataFrame({
109 # ! target_component_synonyms
110 "component_synonym": ExtractedValuesFromColumn(
111 target_components_data, "target_component_synonyms", "component_synonym"),
112 "syn_type": ExtractedValuesFromColumn(
113 target_components_data, "target_component_synonyms", "syn_type"),
114
115 # ! target_component_xrefs
116 "xref_id_target_component_xrefs": ExtractedValuesFromColumn(
117 target_components_data, "target_component_xrefs", "xref_id"),
118 "xref_name_target_component_xrefs": ExtractedValuesFromColumn(
119 target_components_data, "target_component_xrefs", "xref_name"),
120 "xref_src_db_target_component_xrefs": ExtractedValuesFromColumn(
121 target_components_data, "target_component_xrefs", "xref_src_db"),
122 })
123
124 # удаляем столбцы target_component_synonyms и target_component_xrefs.
125 target_components_data = target_components_data.drop(
126 ["target_component_synonyms", "target_component_xrefs"], axis=1)
127 # объединяем DataFrames.
128 target_components_data = pd.concat(
129 [target_components_data, exposed_target_components_data], axis=1)
130
131 # удаляем столбцы cross_references и target_components.
132 data = data.drop(["cross_references", "target_components"], axis=1)
133 # объединяем DataFrames.
134 data = pd.concat([data, exposed_data, target_components_data], axis=1)
135
136 return data
137
138
139@ReTry(attempts_amount=1)
Here is the caller graph for this function:

◆ FilterDownloadedToxicityByCharacteristics()

None functions.FilterDownloadedToxicityByCharacteristics ( str unit_type,
str charact_1,
str charact_2,
str charact_3 )
Фильтрует данные о токсичности из CSV-файла по заданным характеристикам, загружает molfile для каждого соединения и сохраняет результаты в CSV и SDF файлы. Args: unit_type (str): тип единиц измерения (например, "kg" или "m3"). charact_1 (str): название первой характеристики для фильтрации. charact_2 (str): название второй характеристики для фильтрации. charact_3 (str): название третьей характеристики для фильтрации.
769 charact_3: str) -> None:
770 """
771 Фильтрует данные о токсичности из CSV-файла по заданным характеристикам,
772 загружает molfile для каждого соединения и сохраняет результаты в CSV и SDF файлы.
773
774 Args:
775 unit_type (str): тип единиц измерения (например, "kg" или "m3").
776 charact_1 (str): название первой характеристики для фильтрации.
777 charact_2 (str): название второй характеристики для фильтрации.
778 charact_3 (str): название третьей характеристики для фильтрации.
779 """
780 toxicity_config: Config = config["PubChem_download_toxicity"]
781
782 v_logger.info(f"Filtering by characteristics for {unit_type}...")
783
784 # папка для результатов фильтрации.
785 charact_folder_name: str =\
786 f"{toxicity_config["results_folder_name"]}/"\
787 f"{filtering_config["characteristics_folder_name"]}"
788 os.makedirs(charact_folder_name, exist_ok=True)
789
790 # читаем CSV-файл с данными о токсичности.
791 unit_type_df = pd.read_csv(f"{toxicity_config["results_folder_name"]}/"
792 f"{toxicity_config["combined_file_name"]}_{unit_type}.csv",
793 sep=config["csv_separator"],
794 low_memory=False)
795
796 unique_charact_1 = unit_type_df[charact_1].unique()
797 v_logger.info(f"Unique {charact_1}s: {unique_charact_1}.", LogMode.VERBOSELY)
798
799 # заменяем отсутствующие значения времени на "no_exact_time".
800 if charact_2 == "time_period":
801 unit_type_df[charact_2] =\
802 unit_type_df[charact_2].replace(np.nan, "no_exact_time")
803
804 unique_charact_2 = unit_type_df[charact_2].unique()
805 v_logger.info(f"Unique {charact_2}s: {unique_charact_2}.", LogMode.VERBOSELY)
806
807 # словарь для хранения отфильтрованных данных.
808 unique_separated: dict[str, dict[str, pd.DataFrame]] = {}
809
810 # группируем данные по первой и второй характеристикам.
811 for u_charact_1, charact_1_df in unit_type_df.groupby(charact_1):
812 unique_separated.setdefault(str(u_charact_1), {})
813
814 for u_charact_2, charact_2_df in charact_1_df.groupby(charact_2):
815 unique_separated[str(u_charact_1)][str(u_charact_2)] =\
816 charact_2_df.copy()
817
818 unique_charact_3 = unit_type_df[charact_3].unique()
819 v_logger.info(f"Unique {charact_3}s: {unique_charact_3}.", LogMode.VERBOSELY)
820
821 # словарь для хранения окончательно отфильтрованных данных.
822 unique_filtered: dict[str, dict[str, dict[str, pd.DataFrame]]] = {}
823
824 # итерируемся по уникальным значениям характеристик и фильтруем данные.
825 for u_charact_1 in unique_charact_1:
826 v_logger.info("-", LogMode.VERBOSELY)
827 v_logger.info(f"Current {charact_1}: {u_charact_1}.", LogMode.VERBOSELY)
828
829 unique_filtered.setdefault(u_charact_1, {})
830
831 for u_charact_2 in unique_charact_2:
832 v_logger.info(f"Current {charact_2}: {u_charact_2}.", LogMode.VERBOSELY)
833
834 unique_filtered[u_charact_1].setdefault(u_charact_2, {})
835
836 df: pd.DataFrame
837 try:
838 # DataFrame для текущих значений первой и второй характеристик.
839 df = unique_separated[u_charact_1][u_charact_2]
840
841 except KeyError:
842 # если DataFrame не существует, переходим к следующей итерации.
843 continue
844
845 for u_charact_3 in unique_charact_3:
846 # фильтруем DataFrame по третьей характеристике.
847 charact_df = df[df[charact_3] == u_charact_3].copy()
848
849 filtered_file_name = f"{charact_folder_name}/{unit_type}/"\
850 f"{toxicity_config["results_file_name"]}_"\
851 f"{u_charact_1}_{u_charact_2}_{u_charact_3}"
852
853 # если файл уже существует и скачивание пропущено, пропускаем.
854 if os.path.exists(f"{filtered_file_name}.csv") and\
855 config["skip_downloaded"]:
856 v_logger.info(f"{u_charact_1}_{u_charact_2}_{u_charact_3}"
857 " is already downloaded, skip.",
858 LogMode.VERBOSELY)
859 v_logger.info("~", LogMode.VERBOSELY)
860
861 continue
862
863 # устраняем дубликаты по 'cid', используя медиану 'dose'.
864 charact_df = MedianDedupedDF(charact_df, "cid", "dose")
865
866 # перевычисляем pLD.
867 if not charact_df.empty:
868 charact_df["pLD"] = -np.log10(
869 (charact_df["dose"] / charact_df["mw"]) / 1000000)
870
871 # если количество записей в отфильтрованном DataFrame больше или равно
872 # filtering_config["occurrence_characteristics_number"], сохраняем его.
873 if len(charact_df) >=\
874 filtering_config["occurrence_characteristics_number"]:
875 unique_filtered[u_charact_1][u_charact_2][u_charact_3] = charact_df
876
877 os.makedirs(f"{charact_folder_name}/{unit_type}", exist_ok=True)
878
879 charact_df.to_csv(f"{filtered_file_name}.csv")
880
881 # если необходимо скачивать соединения в SDF.
882 if toxicity_config["download_compounds_sdf"]:
883 v_logger.info(f"Saving {unit_type} characteristics to .sdf...",
884 LogMode.VERBOSELY)
885
886 cids: list[str] = list(charact_df["cid"])
887 SaveMolfilesToSDF(data=pd.DataFrame(
888 {"cid": cids,
889 "molfile": GetMolfilesFromCIDs(cids)}),
890 file_name=filtered_file_name,
891 molecule_id_column_name="cid",
892 extra_data=charact_df,
893 indexing_lists=True)
894
895 v_logger.success(f"Saving {unit_type} characteristics to .sdf!",
896 LogMode.VERBOSELY)
897
898 v_logger.success(
899 f"Current {charact_3}: {u_charact_3}, len: "
900 f"{len(unique_filtered[u_charact_1][u_charact_2][u_charact_3])}!",
901 LogMode.VERBOSELY)
902 v_logger.info("~", LogMode.VERBOSELY)
903
904 v_logger.success(f"Filtering by characteristics for {unit_type}!")
Here is the call graph for this function:

◆ GetDataFrameFromUrl()

pd.DataFrame functions.GetDataFrameFromUrl ( str request_url,
float sleep_time )
Скачивает данные из CSV-файла по URL и преобразует их в pandas.DataFrame. Args: request_url (str): URL CSV-файла. sleep_time (float): время ожидания перед повторной попыткой в секундах. Returns: pd.DataFrame: DataFrame, содержащий данные из CSV-файла.
153def GetDataFrameFromUrl(request_url: str, sleep_time: float) -> pd.DataFrame:
154 """
155 Скачивает данные из CSV-файла по URL и преобразует их в pandas.DataFrame.
156
157 Args:
158 request_url (str): URL CSV-файла.
159 sleep_time (float): время ожидания перед повторной попыткой в секундах.
160
161 Returns:
162 pd.DataFrame: DataFrame, содержащий данные из CSV-файла.
163 """
164
165 # получаем ответ на запрос.
166 res = GetResponse(request_url, True, sleep_time)
167
168 # определяем кодировку из заголовков ответа.
169 if res.encoding is None:
170 res.encoding = "utf-8" # (UTF-8, если кодировка не указана)
171
172 # читаем CSV из ответа и преобразуем в DataFrame.
173 return pd.read_csv(StringIO(res.content.decode(res.encoding)))
174
175
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetLinkFromSid()

str functions.GetLinkFromSid ( int sid,
str collection,
int limit )
Формируем URL для скачивания данных из PubChem SDQ API по SID (Structure ID). Args: sid (int): SID соединения. collection (str): коллекция для поиска. limit (int): максимальное количество возвращаемых записей. Returns: str: URL для скачивания данных.
179 ) -> str:
180 """
181 Формируем URL для скачивания данных из PubChem SDQ API по SID (Structure ID).
182
183 Args:
184 sid (int): SID соединения.
185 collection (str): коллекция для поиска.
186 limit (int): максимальное количество возвращаемых записей.
187
188 Returns:
189 str: URL для скачивания данных.
190 """
191
192 def QueryDictToStr(query: dict[str, str]) -> str:
193 """
194 Преобразует словарь с параметрами запроса в строку запроса URL-encoded.
195
196 Args:
197 query (dict[str, str]): словарь с параметрами запроса.
198
199 Returns:
200 str: строка запроса в формате "query={JSON-encoded query}".
201 Пустая строка, если словарь пуст.
202 """
203
204 # если словарь пуст, возвращаем пустую строку.
205 if not query:
206 return ""
207
208 # преобразуем словарь в строку запроса.
209 return f"query={urllib.parse.quote(json.dumps(query))}"
210
211 # формируем словарь с параметрами запроса.
212 query = {
213 "download": "*",
214 "collection": f"{collection}",
215 # "order": ["relevancescore,desc"],
216 "limit": f"{limit}",
217 "where": {
218 "ands": [
219 {"sid": f"{sid}"}
220 ]
221 }
222 }
223
224 # формируем URL для запроса.
225 start = "https://pubchem.ncbi.nlm.nih.gov/sdq/sdqagent.cgi"\
226 "?infmt=json"\
227 "&outfmt=csv"
228
229 return start + "&" + QueryDictToStr(query)
230
231
232# MARK: DownloadCompoundToxicity
233
234
235@ReTry(attempts_amount=1)
Here is the caller graph for this function:

◆ GetMolfileFromCID()

str functions.GetMolfileFromCID ( str cid,
float | None sleep_time = config["PubChem_download_toxicity"]["sleep_time"] )
Возвращает molfile-строку из GET-запроса для соединения с cid из базы PubChem. Args: cid (str): CID соединения. sleep_time (float | None, optional): время ожидания перед повторной попыткой в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"]. Returns: str: molfile-строка.
61 ) -> str:
62 """
63 Возвращает molfile-строку из GET-запроса для соединения с cid из базы PubChem.
64
65 Args:
66 cid (str): CID соединения.
67 sleep_time (float | None, optional): время ожидания перед повторной попыткой
68 в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"].
69
70 Returns:
71 str: molfile-строка.
72 """
73
74 # получаем molfile соединения из PubChem.
75 molfile: str = GetResponse(
76 "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/CID/"
77 f"{cid}/record/SDF?record_type=2d",
78 True,
79 sleep_time).text
80
81 v_logger.info(f"Return molfile (len: {len(molfile)}) for cid: {cid}.",
82 LogMode.VERBOSELY)
83
84 # очищаем molfile от лишних символов.
85 return molfile[molfile.find("\n"):].replace("$$$$", "").rstrip()
86
87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetMolfilesFromCIDs()

list[str] functions.GetMolfilesFromCIDs ( list[str] cids,
float | None sleep_time = config["PubChem_download_toxicity"]["sleep_time"] )
Возвращает список molfile-строк для заданного списка CID. Соединяет CID в строку, разделяет ее на более короткие подстроки, чтобы избежать ограничений на длину URL при запросе к PubChem, и получает molfile для каждого CID. Args: cids (list[str]): список CID соединений. sleep_time (float | None, optional): время ожидания перед повторной попыткой в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"]. Returns: list[str]: список molfile-строк.
90 config["PubChem_download_toxicity"]["sleep_time"]) -> list[str]:
91 """
92 Возвращает список molfile-строк для заданного списка CID.
93 Соединяет CID в строку, разделяет ее на более короткие подстроки, чтобы избежать
94 ограничений на длину URL при запросе к PubChem, и получает molfile для каждого CID.
95
96 Args:
97 cids (list[str]): список CID соединений.
98 sleep_time (float | None, optional): время ожидания перед повторной попыткой
99 в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"].
100
101 Returns:
102 list[str]: список molfile-строк.
103 """
104
105 cids_str = ",".join(str(cid) for cid in cids).replace(" ", "")
106
107 def SplitLongStringWithCommas(s: str) -> list[str]:
108 """
109 Разбивает длинную строку, содержащую CID, разделенные запятыми,
110 на список более коротких строк.
111
112 Это необходимо для избежания ограничений на длину URL при запросе к PubChem.
113 Разбивает так, чтобы длина каждой подстроки не превышала 2000 символов.
114
115 Args:
116 s (str): строка, содержащая CID, разделенные запятыми.
117
118 Returns:
119 list[str]: список строк, содержащих CID, разделенные запятыми.
120 """
121
122 if len(s) <= 2000:
123 return [s]
124
125 chunks = []
126 curr_chunk = ""
127 for cid in s.split(","):
128 if len(curr_chunk) + len(f"{cid},") <= 2000:
129 curr_chunk += f"{cid},"
130
131 else:
132 chunks.append(curr_chunk.rstrip(","))
133 curr_chunk = f"{cid},"
134
135 if curr_chunk not in chunks:
136 chunks.append(curr_chunk.rstrip(","))
137 return chunks
138
139 # получаем molfile для каждой подстроки CID.
140 molfiles_str: str = ""
141 for cids_str_shorter in SplitLongStringWithCommas(cids_str):
142 molfiles_str += GetResponse(
143 "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/CID/"
144 f"{cids_str_shorter}/record/SDF?record_type=2d",
145 True,
146 sleep_time).text
147
148 # разделяем строку с molfile на отдельные molfile и очищаем их.
149 return [f"\n{molfile.split("\n", 1)[1]}"
150 for molfile in molfiles_str.split("\n\n$$$$\n")[:-1]]
151
152
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetRawCellLinesData()

functions.GetRawCellLinesData ( str file_id,
str output_path,
bool print_to_console )
Скачивает zip-файл из Google.Drive, извлекает его содержимое, а затем удаляет zip-файл. Args: file_id: ID файла в Google Drive. output_path: путь к каталогу, куда будут помещены извлеченные файлы. print_to_console (bool): нужно ли выводить логирование в консоль.
54 print_to_console: bool):
55 """
56 Скачивает zip-файл из Google.Drive,
57 извлекает его содержимое, а затем удаляет zip-файл.
58
59 Args:
60 file_id: ID файла в Google Drive.
61 output_path: путь к каталогу, куда будут помещены извлеченные файлы.
62 print_to_console (bool): нужно ли выводить логирование в консоль.
63 """
64
65 os.makedirs(output_path, exist_ok=True)
66
67 url = f"https://drive.google.com/uc?id={file_id}&export=download"
68
69 zip_file_path = f"{output_path}.zip"
70 gdown.download(url, zip_file_path, quiet=(not print_to_console))
71
72 with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
73 zip_ref.extractall(output_path)
74
75 os.remove(zip_file_path)
76
77
78@ReTry(attempts_amount=1)
Here is the caller graph for this function:

◆ GetResponse()

requests.Response functions.GetResponse ( str request_url,
bool stream,
float | None sleep_time = config["PubChem_download_toxicity"]["sleep_time"] )
Отправляет GET-запрос по указанному URL, повторяет попытку в случае ошибки. Args: request_url (str): URL для запроса. stream (bool): если True, ответ будет получен потоком. sleep_time (float | None, optional): время ожидания перед повторной попыткой в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"]. Returns: requests.Response: объект ответа requests.
33 ) -> requests.Response:
34 """
35 Отправляет GET-запрос по указанному URL, повторяет попытку в случае ошибки.
36
37 Args:
38 request_url (str): URL для запроса.
39 stream (bool): если True, ответ будет получен потоком.
40 sleep_time (float | None, optional): время ожидания перед повторной попыткой
41 в секундах. Defaults to config["PubChem_download_toxicity"]["sleep_time"].
42
43 Returns:
44 requests.Response: объект ответа requests.
45 """
46
47 # ждем указанное время, если оно задано.
48 if sleep_time is not None:
49 time.sleep(sleep_time)
50
51 # отправляем GET-запрос.
52 response = requests.get(request_url, stream=stream)
53 response.raise_for_status()
54
55 return response
56
57
Here is the caller graph for this function:

◆ QuerySetActivitiesByIC50()

QuerySet functions.QuerySetActivitiesByIC50 ( str target_id)
Возвращает QuerySet активностей для указанной цели (target_id) на основе IC50. IC50 (Half maximal inhibitory concentration) - полумаксимальная ингибирующая концентрация. Args: target_id (str): Идентификатор цели из базы ChEMBL. Returns: QuerySet: QuerySet, содержащий активности, отфильтрованные по target_id и типу "IC50". Raises: Exception: Если не удается получить данные после нескольких попыток (благодаря декоратору ReTry).
20def QuerySetActivitiesByIC50(target_id: str) -> QuerySet:
21 """
22 Возвращает QuerySet активностей для указанной цели (target_id) на основе IC50.
23
24 IC50 (Half maximal inhibitory concentration) - полумаксимальная ингибирующая
25 концентрация.
26
27 Args:
28 target_id (str): Идентификатор цели из базы ChEMBL.
29
30 Returns:
31 QuerySet: QuerySet, содержащий активности, отфильтрованные по target_id и
32 типу "IC50".
33
34 Raises:
35 Exception: Если не удается получить данные после нескольких попыток
36 (благодаря декоратору ReTry).
37 """
38
39 return new_client.activity.filter( # type: ignore
40 target_chembl_id=target_id).filter(standard_type="IC50")
41
42
43@ReTry()
Here is the caller graph for this function:

◆ QuerySetActivitiesByKi()

QuerySet functions.QuerySetActivitiesByKi ( str target_id)
Возвращает QuerySet активностей для указанной цели (target_id) на основе Ki. Ki (Inhibition constant) - константа ингибирования. Args: target_id (str): Идентификатор цели из базы ChEMBL. Returns: QuerySet: QuerySet, содержащий активности, отфильтрованные по target_id и типу "Ki". Raises: Exception: Если не удается получить данные после нескольких попыток (благодаря декоратору ReTry).
44def QuerySetActivitiesByKi(target_id: str) -> QuerySet:
45 """
46 Возвращает QuerySet активностей для указанной цели (target_id) на основе Ki.
47
48 Ki (Inhibition constant) - константа ингибирования.
49
50 Args:
51 target_id (str): Идентификатор цели из базы ChEMBL.
52
53 Returns:
54 QuerySet: QuerySet, содержащий активности, отфильтрованные по target_id и
55 типу "Ki".
56
57 Raises:
58 Exception: Если не удается получить данные после нескольких попыток
59 (благодаря декоратору ReTry).
60 """
61
62 return new_client.activity.filter( # type: ignore
63 target_chembl_id=target_id).filter(standard_type="Ki")
64
65
Here is the caller graph for this function:

◆ QuerySetAllCellLines()

QuerySet functions.QuerySetAllCellLines ( )
Возвращает все клеточные линии из базы ChEMBL. Returns: QuerySet: набор всех целей
25def QuerySetAllCellLines() -> QuerySet:
26 """
27 Возвращает все клеточные линии из базы ChEMBL.
28
29 Returns:
30 QuerySet: набор всех целей
31 """
32
33 return new_client.cell_line.filter() # type: ignore
34
35
36@ReTry()
Here is the caller graph for this function:

◆ QuerySetAllTargets()

QuerySet functions.QuerySetAllTargets ( )
Возвращает все цели из базы ChEMBL. Returns: QuerySet: набор всех целей
24def QuerySetAllTargets() -> QuerySet:
25 """
26 Возвращает все цели из базы ChEMBL.
27
28 Returns:
29 QuerySet: набор всех целей
30 """
31
32 # получаем все цели из базы ChEMBL.
33 return new_client.target.filter() # type: ignore
34
35
36@ReTry()
Here is the caller graph for this function:

◆ QuerySetCellLinesFromIdList()

QuerySet functions.QuerySetCellLinesFromIdList ( list[str] cell_line_chembl_id_list)
Возвращает клеточные линии по списку id из базы ChEMBL. Args: cell_line_chembl_id_list (list[str]): список id. Returns: QuerySet: набор целей по списку id.
37def QuerySetCellLinesFromIdList(cell_line_chembl_id_list: list[str]) -> QuerySet:
38 """
39 Возвращает клеточные линии по списку id из базы ChEMBL.
40
41 Args:
42 cell_line_chembl_id_list (list[str]): список id.
43
44 Returns:
45 QuerySet: набор целей по списку id.
46 """
47
48 return new_client.cell_line.filter( # type: ignore
49 cell_chembl_id__in=cell_line_chembl_id_list)
50
51
Here is the caller graph for this function:

◆ QuerySetCompoundsByMWRange()

QuerySet functions.QuerySetCompoundsByMWRange ( int less_limit,
int greater_limit )
Возвращает молекулы в диапазоне молекулярной массы [less_limit; greater_limit) из базы ChEMBL. Args: less_limit (int): нижняя граница. greater_limit (int): верхняя граница. Raises: ValueError: границы должны быть больше нуля. ValueError: greater_limit должен быть больше less_limit. Returns: QuerySet: набор молекул в диапазоне.
18def QuerySetCompoundsByMWRange(less_limit: int, greater_limit: int) -> QuerySet:
19 """
20 Возвращает молекулы в диапазоне молекулярной массы
21 [less_limit; greater_limit) из базы ChEMBL.
22
23 Args:
24 less_limit (int): нижняя граница.
25 greater_limit (int): верхняя граница.
26
27 Raises:
28 ValueError: границы должны быть больше нуля.
29 ValueError: greater_limit должен быть больше less_limit.
30
31 Returns:
32 QuerySet: набор молекул в диапазоне.
33 """
34
35 # проверяем, что границы больше нуля.
36 if greater_limit < 0 or less_limit < 0:
37 raise ValueError(
38 "QuerySetMWRangeFilter: limits should be greater zero")
39
40 # проверяем, что верхняя граница больше нижней.
41 if greater_limit < less_limit:
42 raise ValueError(
43 "QuerySetMWRangeFilter: greater_limit should be greater than "
44 "less_limit")
45
46 # фильтруем молекулы по диапазону молекулярной массы.
47 return new_client.molecule.filter( # type: ignore
48 molecule_properties__mw_freebase__lt=greater_limit,
49 molecule_properties__mw_freebase__gte=less_limit)
50
51
Here is the caller graph for this function:

◆ QuerySetTargetsFromIdList()

QuerySet functions.QuerySetTargetsFromIdList ( list[str] target_chembl_id_list)
Возвращает цели по списку id из базы ChEMBL. Args: target_chembl_id_list (list[str]): список id. Returns: QuerySet: набор целей по списку id.
37def QuerySetTargetsFromIdList(target_chembl_id_list: list[str]) -> QuerySet:
38 """
39 Возвращает цели по списку id из базы ChEMBL.
40
41 Args:
42 target_chembl_id_list (list[str]): список id.
43
44 Returns:
45 QuerySet: набор целей по списку id.
46 """
47
48 # получаем цели по списку id из базы ChEMBL.
49 return new_client.target.filter( # type: ignore
50 target_chembl_id__in=target_chembl_id_list)
51
52
Here is the caller graph for this function:

◆ SaveChEMBLMolfilesToSDFByIdList()

functions.SaveChEMBLMolfilesToSDFByIdList ( list[str] molecule_chembl_id_list,
str file_name,
pd.DataFrame extra_data = pd.DataFrame() )
Сохраняет molfiles из списка id в .sdf файл. Args: molecule_chembl_id_list (list[str]): список id. file_name (str): имя файла (без .sdf). extra_data (pd.DataFrame): дополнительная информация.
306 extra_data: pd.DataFrame = pd.DataFrame()):
307 """
308 Сохраняет molfiles из списка id в .sdf файл.
309
310 Args:
311 molecule_chembl_id_list (list[str]): список id.
312 file_name (str): имя файла (без .sdf).
313 extra_data (pd.DataFrame): дополнительная информация.
314 """
315
316 # если список molecule_chembl_id пуст.
317 if not molecule_chembl_id_list:
318 v_logger.warning("Molecules list is empty, nothing to save to .sdf!",
319 LogMode.VERBOSELY)
320 return
321
322 @ReTry()
323 def DataFrameMolfilesFromIdList(molecule_chembl_id_list: list[str]
324 ) -> pd.DataFrame:
325 """
326 Возвращает pd.DataFrame из molfile по каждой молекуле из списка
327 molecule_chembl_id.
328
329 Args:
330 molecule_chembl_id_list (list[str]): список id.
331
332 Returns:
333 pd.DataFrame: DataFrame, который содержит molecule_chembl_id и
334 соотв. molfile.
335 """
336
337 # фильтруем молекулы по списку id.
338 qs_data: QuerySet = new_client.molecule.filter( # type: ignore
339 molecule_chembl_id__in=molecule_chembl_id_list).only([
340 "molecule_chembl_id", "molecule_structures"])
341
342 data = pd.DataFrame(qs_data) # type: ignore
343
344 # извлекаем molfile из структуры молекулы.
345 data["molfile"] = data["molecule_structures"].apply(
346 lambda x: x["molfile"] if isinstance(x, dict) else None)
347
348 # удаляем столбец molecule_structures.
349 data = data.drop(["molecule_structures"], axis=1)
350
351 return data
352
353 v_logger.info("Collecting molfiles to pandas.DataFrame...",
354 LogMode.VERBOSELY)
355
356 # получаем DataFrame из molfiles.
357 data = DataFrameMolfilesFromIdList(molecule_chembl_id_list)
358
359 v_logger.success("Collecting molfiles to pandas.DataFrame!",
360 LogMode.VERBOSELY)
361
362 # сохраняем molfiles в .sdf файл.
363 SaveMolfilesToSDF(data=data,
364 file_name=file_name,
365 molecule_id_column_name="molecule_chembl_id",
366 extra_data=extra_data)

Variable Documentation

◆ filtering_config

Config functions.filtering_config = toxicity_config["filtering"]

◆ toxicity_config

Config functions.toxicity_config = config["PubChem_download_toxicity"]