comparison COBRAxy/flux_simulation_beta.py @ 456:a6e45049c1b9 draft default tip

Uploaded
author francesco_lapi
date Fri, 12 Sep 2025 17:28:45 +0000
parents f49c951c9fe6
children
comparison
equal deleted inserted replaced
455:4e2bc80764b6 456:a6e45049c1b9
1 """
2 Flux sampling and analysis utilities for COBRA models.
3
4 This script supports two modes:
5 - Mode 1 (model_and_bounds=True): load a base model and apply bounds from
6 separate files before sampling.
7 - Mode 2 (model_and_bounds=False): load complete models and sample directly.
8
9 Sampling algorithms supported: OPTGP and CBS. Outputs include flux samples
10 and optional analyses (pFBA, FVA, sensitivity), saved as tabular files.
11 """
12
1 import argparse 13 import argparse
2 import utils.general_utils as utils 14 import utils.general_utils as utils
3 from typing import Optional, List 15 from typing import List
4 import os 16 import os
5 import numpy as np
6 import pandas as pd 17 import pandas as pd
7 import cobra 18 import cobra
8 import utils.CBS_backend as CBS_backend 19 import utils.CBS_backend as CBS_backend
9 from joblib import Parallel, delayed, cpu_count 20 from joblib import Parallel, delayed, cpu_count
10 from cobra.sampling import OptGPSampler 21 from cobra.sampling import OptGPSampler
119 log.write(s + "\n\n") 130 log.write(s + "\n\n")
120 print(s) 131 print(s)
121 132
122 133
123 def write_to_file(dataset: pd.DataFrame, name: str, keep_index:bool=False)->None: 134 def write_to_file(dataset: pd.DataFrame, name: str, keep_index:bool=False)->None:
135 """
136 Write a DataFrame to a TSV file under ARGS.output_path with a given base name.
137
138 Args:
139 dataset: The DataFrame to write.
140 name: Base file name (without extension).
141 keep_index: Whether to keep the DataFrame index in the file.
142
143 Returns:
144 None
145 """
124 dataset.index.name = 'Reactions' 146 dataset.index.name = 'Reactions'
125 dataset.to_csv(ARGS.output_path + "/" + name + ".csv", sep = '\t', index = keep_index) 147 dataset.to_csv(ARGS.output_path + "/" + name + ".csv", sep = '\t', index = keep_index)
126 148
127 ############################ dataset input #################################### 149 ############################ dataset input ####################################
128 def read_dataset(data :str, name :str) -> pd.DataFrame: 150 def read_dataset(data :str, name :str) -> pd.DataFrame:
178 200
179 write_to_file(samplesTotal.T, model_name, True) 201 write_to_file(samplesTotal.T, model_name, True)
180 202
181 for i in range(0, n_batches): 203 for i in range(0, n_batches):
182 os.remove(ARGS.output_path + "/" + model_name + '_'+ str(i)+'_OPTGP.csv') 204 os.remove(ARGS.output_path + "/" + model_name + '_'+ str(i)+'_OPTGP.csv')
183 pass
184 205
185 206
186 def CBS_sampler(model:cobra.Model, model_name:str, n_samples:int=1000, n_batches:int=1, seed:int=0)-> None: 207 def CBS_sampler(model:cobra.Model, model_name:str, n_samples:int=1000, n_batches:int=1, seed:int=0)-> None:
187 """ 208 """
188 Samples using the CBS (Constraint-based Sampling) algorithm and saves the results to CSV files. 209 Samples using the CBS (Constraint-based Sampling) algorithm and saves the results to CSV files.
222 243
223 write_to_file(samplesTotal.T, model_name, True) 244 write_to_file(samplesTotal.T, model_name, True)
224 245
225 for i in range(0, n_batches): 246 for i in range(0, n_batches):
226 os.remove(ARGS.output_path + "/" + model_name + '_'+ str(i)+'_CBS.csv') 247 os.remove(ARGS.output_path + "/" + model_name + '_'+ str(i)+'_CBS.csv')
227 pass
228 248
229 249
230 250
231 def model_sampler_with_bounds(model_input_original: cobra.Model, bounds_path: str, cell_name: str) -> List[pd.DataFrame]: 251 def model_sampler_with_bounds(model_input_original: cobra.Model, bounds_path: str, cell_name: str) -> List[pd.DataFrame]:
232 """ 252 """
391 return df_pFBA, df_FVA, df_sensitivity 411 return df_pFBA, df_FVA, df_sensitivity
392 412
393 ############################# main ########################################### 413 ############################# main ###########################################
394 def main(args :List[str] = None) -> None: 414 def main(args :List[str] = None) -> None:
395 """ 415 """
396 Initializes everything and sets the program in motion based on the fronted input arguments. 416 Initialize and run sampling/analysis based on the frontend input arguments.
397 417
398 Returns: 418 Returns:
399 None 419 None
400 """ 420 """
401 421
404 global ARGS 424 global ARGS
405 ARGS = process_args(args) 425 ARGS = process_args(args)
406 426
407 if not os.path.exists(ARGS.output_path): 427 if not os.path.exists(ARGS.output_path):
408 os.makedirs(ARGS.output_path) 428 os.makedirs(ARGS.output_path)
409
410 #ARGS.bounds = ARGS.input.split(",")
411 #ARGS.bounds_name = ARGS.name.split(",")
412 #ARGS.output_types = ARGS.output_type.split(",")
413 #ARGS.output_type_analysis = ARGS.output_type_analysis.split(",")
414 429
415 # --- Normalize inputs (the tool may pass comma-separated --input and either --name or --names) --- 430 # --- Normalize inputs (the tool may pass comma-separated --input and either --name or --names) ---
416 ARGS.input_files = ARGS.input.split(",") if ARGS.input else [] 431 ARGS.input_files = ARGS.input.split(",") if ARGS.input else []
417 ARGS.file_names = ARGS.name.split(",") 432 ARGS.file_names = ARGS.name.split(",")
418 # output types (required) -> list 433 # output types (required) -> list
437 452
438 base_model = model_utils.build_cobra_model_from_csv(ARGS.model_upload) 453 base_model = model_utils.build_cobra_model_from_csv(ARGS.model_upload)
439 454
440 validation = model_utils.validate_model(base_model) 455 validation = model_utils.validate_model(base_model)
441 456
442 print("\n=== VALIDAZIONE MODELLO ===") 457 print("\n=== MODEL VALIDATION ===")
443 for key, value in validation.items(): 458 for key, value in validation.items():
444 print(f"{key}: {value}") 459 print(f"{key}: {value}")
445 460
446 #Set solver verbosity to 1 to see warning and error messages only. 461 # Set solver verbosity to 1 to see warning and error messages only.
447 base_model.solver.configuration.verbosity = 1 462 base_model.solver.configuration.verbosity = 1
448 463
449 # Process each bounds file with the base model 464 # Process each bounds file with the base model
450 results = Parallel(n_jobs=num_processors)( 465 results = Parallel(n_jobs=num_processors)(
451 delayed(model_sampler_with_bounds)(base_model, bounds_file, cell_name) 466 delayed(model_sampler_with_bounds)(base_model, bounds_file, cell_name)
452 for bounds_file, cell_name in zip(ARGS.input_files, ARGS.file_names) 467 for bounds_file, cell_name in zip(ARGS.input_files, ARGS.file_names)
453 ) 468 )
454 469
496 if("sensitivity" in ARGS.output_type_analysis): 511 if("sensitivity" in ARGS.output_type_analysis):
497 all_sensitivity = pd.concat([result[index_result] for result in results], ignore_index=False) 512 all_sensitivity = pd.concat([result[index_result] for result in results], ignore_index=False)
498 all_sensitivity = all_sensitivity.sort_index() 513 all_sensitivity = all_sensitivity.sort_index()
499 write_to_file(all_sensitivity.T, "sensitivity", True) 514 write_to_file(all_sensitivity.T, "sensitivity", True)
500 515
501 pass 516 return
502 517
503 ############################################################################## 518 ##############################################################################
504 if __name__ == "__main__": 519 if __name__ == "__main__":
505 main() 520 main()