Mercurial > repos > bimib > cobraxy
comparison COBRAxy/flux_simulation_beta.py @ 456:a6e45049c1b9 draft
Uploaded
| author | francesco_lapi | 
|---|---|
| date | Fri, 12 Sep 2025 17:28:45 +0000 | 
| parents | f49c951c9fe6 | 
| children | 73f02860f7d7 | 
   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() | 
