From c1358e9ce193f10129fa5219a42f4f3a24ebd710 Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Fri, 29 May 2020 19:36:26 +0530 Subject: [PATCH 1/8] modified parse_annotation to have only list --- cobra/io/sbml.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/cobra/io/sbml.py b/cobra/io/sbml.py index 5ccc3c7d7..49f86b716 100644 --- a/cobra/io/sbml.py +++ b/cobra/io/sbml.py @@ -1434,14 +1434,9 @@ def _parse_annotations(sbase): provider, identifier = data if provider in annotation: - if isinstance(annotation[provider], string_types): - annotation[provider] = [annotation[provider]] - # FIXME: use a list - if identifier not in annotation[provider]: - annotation[provider].append(identifier) - else: - # FIXME: always in list - annotation[provider] = identifier + if annotation[provider] is None: + annotation[provider] = [] + annotation[provider].append(identifier) return annotation From f2a15ad6ba6cbb2b04e2528d8696e80a2d95618d Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Sat, 30 May 2020 10:02:45 +0530 Subject: [PATCH 2/8] updated code for consistent list in annotation --- cobra/io/sbml.py | 7 +++---- cobra/test/test_io/test_annotation.py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/cobra/io/sbml.py b/cobra/io/sbml.py index 49f86b716..b8f9c026f 100644 --- a/cobra/io/sbml.py +++ b/cobra/io/sbml.py @@ -1433,10 +1433,9 @@ def _parse_annotations(sbase): else: provider, identifier = data - if provider in annotation: - if annotation[provider] is None: - annotation[provider] = [] - annotation[provider].append(identifier) + if provider not in annotation: + annotation[provider] = [] + annotation[provider].append(identifier) return annotation diff --git a/cobra/test/test_io/test_annotation.py b/cobra/test/test_io/test_annotation.py index ae69f3ab8..cbfcb86bf 100644 --- a/cobra/test/test_io/test_annotation.py +++ b/cobra/test/test_io/test_annotation.py @@ -15,9 +15,9 @@ def _check_sbml_annotations(model): assert len(annotation) == 3 for key in ["bigg.model", "doi", "taxonomy"]: assert key in annotation - assert annotation["bigg.model"] == "e_coli_core" - assert annotation["doi"] == "10.1128/ecosalplus.10.2.1" - assert annotation["taxonomy"] == "511145" + assert annotation["bigg.model"] == ["e_coli_core"] + assert annotation["doi"] == ["10.1128/ecosalplus.10.2.1"] + assert annotation["taxonomy"] == ["511145"] # gene annotation # {'asap': 'ABE-0006162', 'ncbigene': '946368', 'uniprot': 'P33221', @@ -26,11 +26,11 @@ def _check_sbml_annotations(model): assert len(annotation) == 5 for key in ["asap", "ncbigene", "uniprot", "ncbigi", "ecogene"]: assert key in annotation - assert annotation["asap"] == "ABE-0006162" - assert annotation["ncbigene"] == "946368" - assert annotation["uniprot"] == "P33221" - assert annotation["ncbigi"] == "gi:16129802" - assert annotation["ecogene"] == "EG11809" + assert annotation["asap"] == ["ABE-0006162"] + assert annotation["ncbigene"] == ["946368"] + assert annotation["uniprot"] == ["P33221"] + assert annotation["ncbigi"] == ["gi:16129802"] + assert annotation["ecogene"] == ["EG11809"] # compartment annotation # FIXME: add tests with first class compartment model @@ -53,7 +53,7 @@ def _check_sbml_annotations(model): "kegg.compound", "seed.compound", "hmdb", "biocyc"]: assert key in annotation assert annotation[ - "inchi"] == "InChI=1S/C3H8O2/c1-3(5)2-4/h3-5H,2H2,1H3/t3-/m0/s1" # noqa: E501 + "inchi"] == ["InChI=1S/C3H8O2/c1-3(5)2-4/h3-5H,2H2,1H3/t3-/m0/s1"] # noqa: E501 # reaction annotation # {'kegg.reaction': 'R00228', 'sbo': 'SBO:0000375', @@ -64,7 +64,7 @@ def _check_sbml_annotations(model): for key in ["kegg.reaction", "sbo", "ec-code", "rhea", "metanetx.reaction", "bigg.reaction", "biocyc"]: assert key in annotation - assert annotation["biocyc"] == 'META:ACETALD-DEHYDROG-RXN' + assert annotation["biocyc"] == ['META:ACETALD-DEHYDROG-RXN'] def test_read_sbml_annotations(data_directory): From 0132f171040f28d3fea723fa4392b8538ed03a6e Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Sun, 31 May 2020 11:40:09 +0530 Subject: [PATCH 3/8] added test to check consistency in annotation --- cobra/io/dict.py | 18 ++++++++++ cobra/test/data/newmini.pickle | Bin 0 -> 29801 bytes cobra/test/test_io/test_json.py | 17 ++++++++++ cobra/test/test_io/test_sbml.py | 58 ++++++++++++++++---------------- 4 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 cobra/test/data/newmini.pickle diff --git a/cobra/io/dict.py b/cobra/io/dict.py index 47a7c0e3f..d744ebbb5 100644 --- a/cobra/io/dict.py +++ b/cobra/io/dict.py @@ -53,6 +53,14 @@ } +def _fix_annotation(annotation): + # Convert single annotation values which are represented as + # as strings as list to have a consistent format + for key in annotation.keys(): + if isinstance(annotation[key], string_types) and key != "sbo": + annotation[key] = [annotation[key]] + + def _fix_type(value): """convert possible types to str, float, and bool""" # Because numpy floats can not be pickled to json @@ -82,6 +90,8 @@ def _update_optional(cobra_object, new_dict, optional_attribute_dict, value = getattr(cobra_object, key) if value is None or value == default: continue + if key == "annotation": + _fix_annotation(value) new_dict[key] = _fix_type(value) @@ -98,6 +108,8 @@ def metabolite_from_dict(metabolite): new_metabolite = Metabolite() for k, v in iteritems(metabolite): setattr(new_metabolite, k, v) + if k == "annotation": + _fix_annotation(v) return new_metabolite @@ -114,6 +126,8 @@ def gene_from_dict(gene): new_gene = Gene(gene["id"]) for k, v in iteritems(gene): setattr(new_gene, k, v) + if k == "annotation": + _fix_annotation(v) return new_gene @@ -143,6 +157,8 @@ def reaction_from_dict(reaction, model): for met, coeff in iteritems(v))) else: setattr(new_reaction, k, v) + if k == "annotation": + _fix_annotation(v) return new_reaction @@ -226,4 +242,6 @@ def model_from_dict(obj): for k, v in iteritems(obj): if k in {'id', 'name', 'notes', 'compartments', 'annotation'}: setattr(model, k, v) + if k == "annotation": + _fix_annotation(v) return model diff --git a/cobra/test/data/newmini.pickle b/cobra/test/data/newmini.pickle new file mode 100644 index 0000000000000000000000000000000000000000..78645fbddfd7bfe103844f8627ddf6d0b900ab23 GIT binary patch literal 29801 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 Date: Sun, 31 May 2020 11:47:06 +0530 Subject: [PATCH 4/8] a few modifications --- cobra/test/data/mini.pickle | Bin 32200 -> 29801 bytes cobra/test/data/newmini.pickle | Bin 29801 -> 0 bytes cobra/test/test_io/test_sbml.py | 8 ++++---- 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 cobra/test/data/newmini.pickle diff --git a/cobra/test/data/mini.pickle b/cobra/test/data/mini.pickle index 2942d27db340400e13b7f99d45a617c7e1381efe..78645fbddfd7bfe103844f8627ddf6d0b900ab23 100644 GIT binary patch literal 29801 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 diff --git a/cobra/test/data/newmini.pickle b/cobra/test/data/newmini.pickle deleted file mode 100644 index 78645fbddfd7bfe103844f8627ddf6d0b900ab23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29801 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 Date: Mon, 1 Jun 2020 17:59:44 +0530 Subject: [PATCH 5/8] added support for handling list of list format for annotation --- cobra/io/dict.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/cobra/io/dict.py b/cobra/io/dict.py index d744ebbb5..ecb949ef2 100644 --- a/cobra/io/dict.py +++ b/cobra/io/dict.py @@ -10,6 +10,7 @@ from cobra.core import Gene, Metabolite, Model, Reaction from cobra.util.solver import set_objective +from cobra.io.sbml import _parse_annotation_info _REQUIRED_REACTION_ATTRIBUTES = [ @@ -54,12 +55,31 @@ def _fix_annotation(annotation): + # if annotation is in the form of a list of list, convert it in + # right format first i.e in a dict format + if isinstance(annotation, list): + dict_anno = {} + for item in annotation: + data = _parse_annotation_info(item[1]) + if data is None: + continue + else: + provider, identifier = data + + if provider not in dict_anno: + dict_anno[provider] = [] + dict_anno[provider].append(identifier) + + annotation = dict_anno + # Convert single annotation values which are represented as # as strings as list to have a consistent format for key in annotation.keys(): if isinstance(annotation[key], string_types) and key != "sbo": annotation[key] = [annotation[key]] + return annotation + def _fix_type(value): """convert possible types to str, float, and bool""" @@ -107,9 +127,9 @@ def metabolite_to_dict(metabolite): def metabolite_from_dict(metabolite): new_metabolite = Metabolite() for k, v in iteritems(metabolite): - setattr(new_metabolite, k, v) if k == "annotation": - _fix_annotation(v) + v = _fix_annotation(v) + setattr(new_metabolite, k, v) return new_metabolite @@ -125,9 +145,9 @@ def gene_to_dict(gene): def gene_from_dict(gene): new_gene = Gene(gene["id"]) for k, v in iteritems(gene): - setattr(new_gene, k, v) if k == "annotation": - _fix_annotation(v) + v = _fix_annotation(v) + setattr(new_gene, k, v) return new_gene @@ -156,9 +176,9 @@ def reaction_from_dict(reaction, model): (model.metabolites.get_by_id(str(met)), coeff) for met, coeff in iteritems(v))) else: - setattr(new_reaction, k, v) if k == "annotation": - _fix_annotation(v) + v = _fix_annotation(v) + setattr(new_reaction, k, v) return new_reaction @@ -241,7 +261,7 @@ def model_from_dict(obj): set_objective(model, coefficients) for k, v in iteritems(obj): if k in {'id', 'name', 'notes', 'compartments', 'annotation'}: - setattr(model, k, v) if k == "annotation": - _fix_annotation(v) + v = _fix_annotation(v) + setattr(model, k, v) return model From 91e79c371750a69032cd0885ea96d9531800f881 Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Tue, 2 Jun 2020 16:53:17 +0530 Subject: [PATCH 6/8] added test for checking list of list format --- cobra/io/dict.py | 2 +- cobra/io/sbml.py | 4 ++-- cobra/test/data/invalid_annotation_format.json | 4 ++++ cobra/test/test_io/test_annotation_format.py | 10 +++++++--- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cobra/io/dict.py b/cobra/io/dict.py index ecb949ef2..e9a242b9f 100644 --- a/cobra/io/dict.py +++ b/cobra/io/dict.py @@ -10,7 +10,7 @@ from cobra.core import Gene, Metabolite, Model, Reaction from cobra.util.solver import set_objective -from cobra.io.sbml import _parse_annotation_info +from cobra.io.sbml import parse_annotation_info _REQUIRED_REACTION_ATTRIBUTES = [ diff --git a/cobra/io/sbml.py b/cobra/io/sbml.py index b8f9c026f..d48075ee1 100644 --- a/cobra/io/sbml.py +++ b/cobra/io/sbml.py @@ -1427,7 +1427,7 @@ def _parse_annotations(sbase): # FIXME: read and store the qualifier uri = cvterm.getResourceURI(k) - data = _parse_annotation_info(uri) + data = parse_annotation_info(uri) if data is None: continue else: @@ -1440,7 +1440,7 @@ def _parse_annotations(sbase): return annotation -def _parse_annotation_info(uri): +def parse_annotation_info(uri): """Parses provider and term from given identifiers annotation uri. Parameters diff --git a/cobra/test/data/invalid_annotation_format.json b/cobra/test/data/invalid_annotation_format.json index 96855b863..a17edbcee 100644 --- a/cobra/test/data/invalid_annotation_format.json +++ b/cobra/test/data/invalid_annotation_format.json @@ -12,6 +12,10 @@ [ "CHEBI", "http://identifiers.org/chebi/CHEBI:11981" + ], + [ + "CHEBI", + "http://identifiers.org/chebi/CHEBI:17847" ] ] } diff --git a/cobra/test/test_io/test_annotation_format.py b/cobra/test/test_io/test_annotation_format.py index 1b5fea619..a79ff5d3f 100644 --- a/cobra/test/test_io/test_annotation_format.py +++ b/cobra/test/test_io/test_annotation_format.py @@ -21,7 +21,11 @@ def test_load_json_model_valid(data_directory, tmp_path): def test_load_json_model_invalid(data_directory): - """Test that loading an invalid annotation from JSON raises TypeError""" + """Test loading an annotation in the form of list of list""" path = join(data_directory, "invalid_annotation_format.json") - with pytest.raises(TypeError): - model = load_json_model(path) + expected = { + 'kegg.compound': ['C01468'], + 'chebi': ['CHEBI:11981', 'CHEBI:17847'] + } + model = load_json_model(path) + assert model.metabolites[0].annotation == expected From 470f153342eb6e0b1edda7dbd4310c832c188a02 Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Tue, 2 Jun 2020 17:10:01 +0530 Subject: [PATCH 7/8] modified imports --- cobra/io/__init__.py | 3 +-- cobra/io/dict.py | 4 ++-- cobra/test/test_io/test_sbml.py | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cobra/io/__init__.py b/cobra/io/__init__.py index ca889ceda..5ac69fe57 100644 --- a/cobra/io/__init__.py +++ b/cobra/io/__init__.py @@ -5,6 +5,5 @@ from cobra.io.dict import model_from_dict, model_to_dict from cobra.io.json import from_json, load_json_model, save_json_model, to_json from cobra.io.mat import load_matlab_model, save_matlab_model -from cobra.io.sbml import read_sbml_model, write_sbml_model, \ - validate_sbml_model +from cobra.io.sbml import read_sbml_model, validate_sbml_model, write_sbml_model from cobra.io.yaml import from_yaml, load_yaml_model, save_yaml_model, to_yaml diff --git a/cobra/io/dict.py b/cobra/io/dict.py index e9a242b9f..fee26645b 100644 --- a/cobra/io/dict.py +++ b/cobra/io/dict.py @@ -9,8 +9,8 @@ from six import iteritems, string_types from cobra.core import Gene, Metabolite, Model, Reaction -from cobra.util.solver import set_objective from cobra.io.sbml import parse_annotation_info +from cobra.util.solver import set_objective _REQUIRED_REACTION_ATTRIBUTES = [ @@ -60,7 +60,7 @@ def _fix_annotation(annotation): if isinstance(annotation, list): dict_anno = {} for item in annotation: - data = _parse_annotation_info(item[1]) + data = parse_annotation_info(item[1]) if data is None: continue else: diff --git a/cobra/test/test_io/test_sbml.py b/cobra/test/test_io/test_sbml.py index 98f87ede2..8d9e87b69 100644 --- a/cobra/test/test_io/test_sbml.py +++ b/cobra/test/test_io/test_sbml.py @@ -360,7 +360,7 @@ def test_gprs(data_directory, tmp_path): def test_identifiers_annotation(): - from cobra.io.sbml import _parse_annotation_info + from cobra.io.sbml import parse_annotation_info for uri in [ "http://identifiers.org/chebi/CHEBI:000123", @@ -368,7 +368,7 @@ def test_identifiers_annotation(): "http://identifiers.org/CHEBI:000123", "https://identifiers.org/CHEBI:000123", ]: - data = _parse_annotation_info(uri) + data = parse_annotation_info(uri) assert data assert data[0] == "chebi" assert data[1] == "CHEBI:000123" @@ -379,7 +379,7 @@ def test_identifiers_annotation(): "http://identifiers.org/taxonomy:9602", "https://identifiers.org/taxonomy:9602", ]: - data = _parse_annotation_info(uri) + data = parse_annotation_info(uri) assert data assert data[0] == "taxonomy" assert data[1] == "9602" @@ -388,7 +388,7 @@ def test_identifiers_annotation(): "http://identifier.org/taxonomy/9602", "https://test.com", ]: - data = _parse_annotation_info(uri) + data = parse_annotation_info(uri) assert data is None From 351d5c3df9a8b8e691a3f298809205d1cc1b6bd3 Mon Sep 17 00:00:00 2001 From: HemantYadav Date: Fri, 5 Jun 2020 00:42:06 +0530 Subject: [PATCH 8/8] modified code using defaultdict --- cobra/io/dict.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cobra/io/dict.py b/cobra/io/dict.py index fee26645b..d43174463 100644 --- a/cobra/io/dict.py +++ b/cobra/io/dict.py @@ -2,7 +2,7 @@ from __future__ import absolute_import -from collections import OrderedDict +from collections import OrderedDict, defaultdict from operator import attrgetter, itemgetter from numpy import bool_, float_ @@ -58,7 +58,7 @@ def _fix_annotation(annotation): # if annotation is in the form of a list of list, convert it in # right format first i.e in a dict format if isinstance(annotation, list): - dict_anno = {} + dict_anno = defaultdict(list) for item in annotation: data = parse_annotation_info(item[1]) if data is None: @@ -66,8 +66,6 @@ def _fix_annotation(annotation): else: provider, identifier = data - if provider not in dict_anno: - dict_anno[provider] = [] dict_anno[provider].append(identifier) annotation = dict_anno