From 33eee184f0861daf86c45961401b2353786d0d1f Mon Sep 17 00:00:00 2001 From: Sylvain Soliman <Sylvain.Soliman@inria.fr> Date: Sun, 12 Feb 2023 15:42:53 +0100 Subject: [PATCH] Allow to fix input/KO/KI values via a CSV file --- casq/celldesigner2qual.py | 9 ++++++++- casq/write.py | 40 ++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/casq/celldesigner2qual.py b/casq/celldesigner2qual.py index 6cbbaa1..6caad2c 100755 --- a/casq/celldesigner2qual.py +++ b/casq/celldesigner2qual.py @@ -76,6 +76,13 @@ def main(): size is smaller than S. A negative S leads to keep only the biggest(s) connected component(s)""", ) + parser.add_argument( + "-f", + "--fixed", + type=argparse.FileType(), + help="""A CSV file containing input values or knock-ins/knock-outs, + one per line, with name in the first column and the value in the second.""" + ) if sys.version_info >= (3, 8, 0): parser.add_argument( "-u", @@ -162,7 +169,7 @@ def main(): args.outfile, info, args.granularity, args.input, False, args.colourConstant ) else: - write_qual(args.outfile, info, width, height, remove=args.remove, sif=args.sif) + write_qual(args.outfile, info, width, height, remove=args.remove, sif=args.sif, fixed=args.fixed) if args.csv and args.outfile != sys.stdout: write_csv(args.outfile, info) diff --git a/casq/write.py b/casq/write.py index 59e4a66..e132204 100644 --- a/casq/write.py +++ b/casq/write.py @@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. import csv import xml.etree.ElementTree as etree from itertools import chain, repeat -from typing import List, Optional, Tuple # noqa: F401 +from typing import IO, List, Optional, Tuple # noqa: F401 from loguru import logger # type: ignore @@ -34,7 +34,13 @@ NEGATIVE = ("INHIBITION", "NEGATIVE_INFLUENCE", "UNKNOWN_INHIBITION") def write_qual( - filename: str, info, width: str, height: str, remove: int = 0, sif: bool = False + filename: str, + info, + width: str, + height: str, + remove: int = 0, + sif: bool = False, + fixed: IO = None, ): # pylint: disable=too-many-arguments, too-many-locals """Write the SBML qual with layout file for our model.""" @@ -66,11 +72,20 @@ def write_qual( qlist = etree.SubElement(model, "qual:listOfQualitativeSpecies") tlist = etree.SubElement(model, "qual:listOfTransitions") graph = nx.DiGraph() + initial = {} + if fixed: + # dialect = csv.Sniffer().sniff(fixed.read(1024)) + # fixed.seek(0) + for row in csv.reader(fixed): + if row[0] in info: + info[row[0]]["transitions"] = [] + initial[row[0]] = row[1] + add_transitions(tlist, info, graph) remove_connected_components(tlist, info, graph, remove) if sif: write_sif(filename, info, graph) - add_qual_species(layout, qlist, info) + add_qual_species(layout, qlist, info, initial) etree.ElementTree(root).write(filename, encoding="utf-8", xml_declaration=True) @@ -130,7 +145,7 @@ def write_sif(sbml_filename: str, info, graph: nx.DiGraph): ) -def add_qual_species(layout: etree.Element, qlist: etree.Element, info): +def add_qual_species(layout: etree.Element, qlist: etree.Element, info, initial): """Create layout sub-elements and species.""" llist = etree.SubElement(layout, "layout:listOfAdditionalGraphicalObjects") for species, data in info.items(): @@ -152,16 +167,19 @@ def add_qual_species(layout: etree.Element, qlist: etree.Element, info): constant = "false" else: constant = "true" + attribs = { + "qual:maxLevel": "1", + "qual:compartment": "comp1", + "qual:name": data["name"], + "qual:constant": constant, + "qual:id": species, + } + if species in initial: + attribs["qual:initialLevel"] = initial[species] qspecies = etree.SubElement( qlist, "qual:qualitativeSpecies", - { - "qual:maxLevel": "1", - "qual:compartment": "comp1", - "qual:name": data["name"], - "qual:constant": constant, - "qual:id": species, - }, + attribs, ) add_annotation(qspecies, data["annotations"]) -- GitLab