| 
491
 | 
     1 """
 | 
| 
 | 
     2 Convert a tabular (CSV/TSV/Tabular) description of a COBRA model into a COBRA file.
 | 
| 
 | 
     3 
 | 
| 
 | 
     4 Supported output formats: SBML, JSON, MATLAB (.mat), YAML.
 | 
| 
 | 
     5 The script logs to a user-provided file for easier debugging in Galaxy.
 | 
| 
 | 
     6 """
 | 
| 
 | 
     7 
 | 
| 
 | 
     8 import os
 | 
| 
 | 
     9 import cobra
 | 
| 
 | 
    10 import argparse
 | 
| 
 | 
    11 from typing import List
 | 
| 
 | 
    12 import logging
 | 
| 
 | 
    13 import utils.model_utils as modelUtils
 | 
| 
 | 
    14 
 | 
| 
 | 
    15 ARGS : argparse.Namespace
 | 
| 
 | 
    16 def process_args(args: List[str] = None) -> argparse.Namespace:
 | 
| 
 | 
    17     """
 | 
| 
 | 
    18     Parse command-line arguments for the CSV-to-COBRA conversion tool.
 | 
| 
 | 
    19 
 | 
| 
 | 
    20     Returns:
 | 
| 
 | 
    21         argparse.Namespace: Parsed arguments.
 | 
| 
 | 
    22     """
 | 
| 
 | 
    23     parser = argparse.ArgumentParser(
 | 
| 
 | 
    24     usage="%(prog)s [options]",
 | 
| 
 | 
    25     description="Convert a tabular/CSV file to a COBRA model"
 | 
| 
 | 
    26     )
 | 
| 
 | 
    27 
 | 
| 
 | 
    28 
 | 
| 
 | 
    29     parser.add_argument("--out_log", type=str, required=True,
 | 
| 
 | 
    30     help="Output log file")
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 
 | 
| 
 | 
    33     parser.add_argument("--input", type=str, required=True,
 | 
| 
 | 
    34     help="Input tabular file (CSV/TSV)")
 | 
| 
 | 
    35 
 | 
| 
 | 
    36 
 | 
| 
 | 
    37     parser.add_argument("--format", type=str, required=True, choices=["sbml", "json", "mat", "yaml"],
 | 
| 
 | 
    38     help="Model format (SBML, JSON, MATLAB, YAML)")
 | 
| 
 | 
    39 
 | 
| 
 | 
    40 
 | 
| 
 | 
    41     parser.add_argument("--output", type=str, required=True,
 | 
| 
 | 
    42     help="Output model file path")
 | 
| 
 | 
    43 
 | 
| 
 | 
    44 
 | 
| 
 | 
    45     parser.add_argument("--tool_dir", type=str, default=os.path.dirname(__file__),
 | 
| 
 | 
    46     help="Tool directory (passed from Galaxy as $__tool_directory__)")
 | 
| 
 | 
    47 
 | 
| 
 | 
    48 
 | 
| 
 | 
    49     return parser.parse_args(args)
 | 
| 
 | 
    50 
 | 
| 
 | 
    51 
 | 
| 
 | 
    52 ###############################- ENTRY POINT -################################
 | 
| 
 | 
    53 
 | 
| 
 | 
    54 def main(args: List[str] = None) -> None:
 | 
| 
 | 
    55     """
 | 
| 
 | 
    56     Entry point: parse arguments, build the COBRA model from a CSV/TSV file,
 | 
| 
 | 
    57     and save it in the requested format.
 | 
| 
 | 
    58 
 | 
| 
 | 
    59     Returns:
 | 
| 
 | 
    60         None
 | 
| 
 | 
    61     """
 | 
| 
 | 
    62     global ARGS
 | 
| 
 | 
    63     ARGS = process_args(args)
 | 
| 
 | 
    64 
 | 
| 
 | 
    65     # configure logging to the requested log file (overwrite each run)
 | 
| 
 | 
    66     logging.basicConfig(filename=ARGS.out_log,
 | 
| 
 | 
    67                         level=logging.DEBUG,
 | 
| 
 | 
    68                         format='%(asctime)s %(levelname)s: %(message)s',
 | 
| 
 | 
    69                         filemode='w')
 | 
| 
 | 
    70 
 | 
| 
 | 
    71     logging.info('Starting fromCSVtoCOBRA tool')
 | 
| 
 | 
    72     logging.debug('Args: input=%s format=%s output=%s tool_dir=%s', ARGS.input, ARGS.format, ARGS.output, ARGS.tool_dir)
 | 
| 
 | 
    73 
 | 
| 
 | 
    74     try:
 | 
| 
 | 
    75         # Basic sanity checks
 | 
| 
 | 
    76         if not os.path.exists(ARGS.input):
 | 
| 
 | 
    77             logging.error('Input file not found: %s', ARGS.input)
 | 
| 
 | 
    78 
 | 
| 
 | 
    79         out_dir = os.path.dirname(os.path.abspath(ARGS.output))
 | 
| 
 | 
    80         
 | 
| 
 | 
    81         if out_dir and not os.path.isdir(out_dir):
 | 
| 
 | 
    82             try:
 | 
| 
 | 
    83                 os.makedirs(out_dir, exist_ok=True)
 | 
| 
 | 
    84                 logging.info('Created missing output directory: %s', out_dir)
 | 
| 
 | 
    85             except Exception as e:
 | 
| 
 | 
    86                 logging.exception('Cannot create output directory: %s', out_dir)
 | 
| 
 | 
    87 
 | 
| 
 | 
    88         model = modelUtils.build_cobra_model_from_csv(ARGS.input)
 | 
| 
 | 
    89 
 | 
| 
 | 
    90         # Save model in requested format
 | 
| 
 | 
    91         if ARGS.format == "sbml":
 | 
| 
 | 
    92             cobra.io.write_sbml_model(model, ARGS.output)
 | 
| 
 | 
    93         elif ARGS.format == "json":
 | 
| 
 | 
    94             cobra.io.save_json_model(model, ARGS.output)
 | 
| 
 | 
    95         elif ARGS.format == "mat":
 | 
| 
 | 
    96             cobra.io.save_matlab_model(model, ARGS.output)
 | 
| 
 | 
    97         elif ARGS.format == "yaml":
 | 
| 
 | 
    98             cobra.io.save_yaml_model(model, ARGS.output)
 | 
| 
 | 
    99         else:
 | 
| 
 | 
   100             logging.error('Unknown format requested: %s', ARGS.format)
 | 
| 
 | 
   101             print(f"ERROR: Unknown format: {ARGS.format}")
 | 
| 
 | 
   102 
 | 
| 
 | 
   103 
 | 
| 
 | 
   104         logging.info('Model successfully written to %s (format=%s)', ARGS.output, ARGS.format)
 | 
| 
 | 
   105 
 | 
| 
 | 
   106     except Exception:
 | 
| 
 | 
   107         # Log full traceback to the out_log so Galaxy users/admins can see what happened
 | 
| 
 | 
   108         logging.exception('Unhandled exception in fromCSVtoCOBRA')
 | 
| 
 | 
   109 
 | 
| 
 | 
   110 
 | 
| 
 | 
   111 if __name__ == '__main__':
 | 
| 
 | 
   112     main()
 |