diff --git a/release-notes/next-release.md b/release-notes/next-release.md index a38777b5a..8bb9bbe10 100644 --- a/release-notes/next-release.md +++ b/release-notes/next-release.md @@ -2,6 +2,8 @@ ## New features +* View number of genes in model notebook representation. + ## Fixes * serializes GPRs to strings to avoid massive storage usage diff --git a/src/cobra/core/dictlist.py b/src/cobra/core/dictlist.py index dad2c71b4..32d45ea85 100644 --- a/src/cobra/core/dictlist.py +++ b/src/cobra/core/dictlist.py @@ -16,6 +16,7 @@ ) import numpy as np +import pandas as pd from .object import Object @@ -542,3 +543,28 @@ def __dir__(self) -> list: attributes.append("_dict") attributes.extend(self._dict.keys()) return attributes + + def to_df(self): + """Convert to a pandas dataframe.""" + item = None + columns = [] + + if self: + item = self[0] + columns = [col for col in item._DF_ATTRS if col != "id"] + + data = [] + ids = [] + + for item in self: + ids.append(item.id) + data.append([getattr(item, attr) for attr in columns]) + + df = pd.DataFrame(columns=columns, data=data, index=ids) + + return df + + def _repr_html_(self): + """Display as HTML.""" + df = self.to_df() + return df._repr_html_() diff --git a/src/cobra/core/formula.py b/src/cobra/core/formula.py index 8aeab23bf..fbbb33d58 100644 --- a/src/cobra/core/formula.py +++ b/src/cobra/core/formula.py @@ -22,6 +22,8 @@ class Formula(Object): A legal formula string contains only letters and numbers. """ + _DF_ATTRS = ["formula"] + def __init__(self, formula: Optional[str] = None, **kwargs) -> None: """Initialize a formula. diff --git a/src/cobra/core/gene.py b/src/cobra/core/gene.py index 4d8a13576..e6e1a1543 100644 --- a/src/cobra/core/gene.py +++ b/src/cobra/core/gene.py @@ -204,6 +204,8 @@ class Gene(Species): used. """ + _DF_ATTRS = Species._DF_ATTRS + # noinspection PyShadowingBuiltins def __init__(self, id: str = None, name: str = "", functional: bool = True) -> None: """Initialize a gene. diff --git a/src/cobra/core/group.py b/src/cobra/core/group.py index ac2e508b3..39651ff49 100644 --- a/src/cobra/core/group.py +++ b/src/cobra/core/group.py @@ -38,6 +38,8 @@ class Group(Object): or member is involved in a disease phenotype). """ + _DF_ATTRS = ["id", "name", "kind"] + KIND_TYPES = ("collection", "classification", "partonomy") def __init__( diff --git a/src/cobra/core/metabolite.py b/src/cobra/core/metabolite.py index 6b3d31dc9..131a94e57 100644 --- a/src/cobra/core/metabolite.py +++ b/src/cobra/core/metabolite.py @@ -44,6 +44,8 @@ class Metabolite(Species): Compartment of the metabolite. """ + _DF_ATTRS = Species._DF_ATTRS + ["formula", "compartment", "charge"] + # noinspection PyShadowingBuiltins def __init__( self, diff --git a/src/cobra/core/model.py b/src/cobra/core/model.py index 597c3802b..156744ead 100644 --- a/src/cobra/core/model.py +++ b/src/cobra/core/model.py @@ -1500,6 +1500,9 @@ def _repr_html_(self) -> str: Number of reactions {len(self.reactions)} + + Number of genes + {len(self.genes)} Number of groups {len(self.groups)} diff --git a/src/cobra/core/reaction.py b/src/cobra/core/reaction.py index 0623ae170..4508096ec 100644 --- a/src/cobra/core/reaction.py +++ b/src/cobra/core/reaction.py @@ -85,6 +85,15 @@ class Reaction(Object): Further keyword arguments are passed on to the parent class. """ + _DF_ATTRS = [ + "id", + "name", + "subsystem", + "gene_reaction_rule", + "lower_bound", + "upper_bound", + ] + # noinspection PyShadowingBuiltins def __init__( self, diff --git a/src/cobra/core/species.py b/src/cobra/core/species.py index 39749fcd0..413c038ec 100644 --- a/src/cobra/core/species.py +++ b/src/cobra/core/species.py @@ -25,6 +25,8 @@ class Species(Object): A human readable name. """ + _DF_ATTRS = ["id", "name"] + # noinspection PyShadowingBuiltins def __init__( self, id: Optional[str] = None, name: Optional[str] = None, **kwargs diff --git a/tests/test_core/test_dictlist.py b/tests/test_core/test_dictlist.py index 5b2d35586..b5630f542 100644 --- a/tests/test_core/test_dictlist.py +++ b/tests/test_core/test_dictlist.py @@ -5,6 +5,7 @@ from pickle import HIGHEST_PROTOCOL, dumps, loads from typing import Tuple +import pandas as pd import pytest from cobra.core import DictList, Object @@ -468,3 +469,38 @@ def test_union(dict_list: Tuple[Object, DictList]) -> None: # Add only 1 element assert len(test_list) == 2 assert test_list.index("test2") == 1 + +def test_to_df(dict_list: Tuple[Object, DictList]) -> None: + """Test to_df for dictlist. + + Parameters + ---------- + dict_list : tuple + The fixture for filled dictlist. + + """ + _, test_list = dict_list + test_list.name = "foo" + df = test_list.to_df() + assert isinstance(df, pd.DataFrame) + assert len(df) == 1 + assert "id" in df.columns + assert "test1" in df["id"].values + assert "name" in df.columns + assert "foo" in df["name"].values + +def test__repr_html(dict_list: Tuple[Object, DictList]) -> None: + """Test _repr_html_ for dictlist. + + Parameters + ---------- + dict_list : tuple + The fixture for filled dictlist. + + """ + _, test_list = dict_list + test_list.name = "foo" + html = test_list._repr_html_() + assert isinstance(html, str) + assert "test1" in html + assert "foo" in html \ No newline at end of file