diff tools/myTools/bin/sfa/base.py @ 1:7e5c71b2e71f draft default tip

Uploaded
author laurenmarazzi
date Wed, 22 Dec 2021 16:00:34 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/myTools/bin/sfa/base.py	Wed Dec 22 16:00:34 2021 +0000
@@ -0,0 +1,344 @@
+import os
+import sys
+if sys.version_info <= (2, 8):
+    from builtins import super
+
+# from abc import ABC, abstractmethod
+import abc
+import copy
+
+import pandas as pd
+import six
+import sfa.utils
+
+__all__ = ['Algorithm', 'Data', 'Result']
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ContainerItem():
+    """
+    The base class that defines the item object of
+    ``sfa.containers.Container``.
+
+    """
+    def __init__(self, abbr=None, name=None):
+        self._abbr = abbr
+        self._name = name
+
+    def __str__(self):
+        return self._abbr
+
+    def __repr__(self):
+        class_name = self.__class__.__name__
+        return "%s object" % (class_name)
+
+    @property
+    def abbr(self):
+        """Abbreviation or symbol representing this item.
+        """
+        return self._abbr
+
+    @abbr.setter
+    def abbr(self, val):
+        self._abbr =val
+
+    @property
+    def name(self):
+        """Full name or description of this item.
+        """
+        return self._name
+
+    @name.setter
+    def name(self, val):
+        self._name = val
+
+
+class ParameterSet(sfa.utils.FrozenClass):
+    """The base class of ParameterSet objects.
+    """
+
+    def __init__(self, abbr):
+        """
+        """
+        super().__init__(abbr)
+
+
+class Algorithm(ContainerItem):
+    """The base class of Algorithm classes.
+
+    Attributes
+    ----------
+    abbr : str
+    name : str
+    data : sfa.base.Data
+    params : sfa.base.ParameterSet
+    result : sfa.base.Result
+
+    Examples
+    --------
+        >>> class AnAlgorithm(sfa.base.Algorithm):
+                # Definition of algorithm ...
+                ...
+        
+        >>> alg = AnAlgorithm()
+        >>> alg.params = params_obj # Parameters of the algorithm
+        >>> alg.data = data_obj # Data to be analyzed by the algorithm
+        >>> alg.initialize()
+        >>> res = alg.compute()
+        
+    """
+    def __init__(self, abbr):
+        super().__init__(abbr)
+        self._data = None
+        self._params = None
+        self._result = None
+
+    def copy(self, is_deep=False):
+        """
+
+        """
+        if is_deep:
+            copy.deepcopy(self)
+        else:
+            return copy.copy(self)
+
+    # Read-only properties
+    @property
+    def result(self):
+        """The object of ``sfa.base.Result``.
+           The result of computing the batch.
+        """
+        return self._result
+
+    # Read & write properties
+    @property
+    def params(self):
+        """The object of ``sfa.base.ParameterSet``.
+           Parameters of the algorithm can accessed
+           through this member.
+        """
+        return self._params
+        
+    @params.setter
+    def params(self, obj):
+        self._params = obj    
+    
+    @property
+    def data(self):
+        """The object of ``sfa.base.Data``.
+            Data to be processed based on the algorithm
+            can accessed through this member.
+        """
+        return self._data
+        
+    @data.setter
+    def data(self, obj):
+        self._data = obj
+
+    def initialize(self, network=True, ba=True):
+        """
+        """
+        if network:
+            self.initialize_network()
+
+        if ba:
+            self.initialize_basal_activity()
+
+    def initialize_network(self):
+        """Initialize the data structures related to network.
+        """
+        pass
+
+    def initialize_basal_activity(self):
+        """Initialize the basal activity, :math:`b`.
+        """
+        pass
+
+    @abc.abstractmethod
+    def compute(self, b,pi):
+        r"""Process the assigned data
+            with the given basal activity, :math:`b`.
+
+        Parameters
+        ----------
+        b : numpy.ndarray
+            1D array of basal activity.
+
+        pi: list
+            list of fixed node perturbations
+        Returns
+        -------
+        x : numpy.ndarray
+            1D-array object of activity at steady-state.
+        """
+        raise NotImplementedError("compute() should be implemented")
+
+    @abc.abstractmethod
+    def compute_batch(self):
+        """Process the assigned data that contains a batch data.
+           The result is stored in ``result`` member.
+        """
+        raise NotImplementedError("compute_batch() should be implemented")
+
+# end of class Algorithm        
+
+
+class Data(ContainerItem):
+    def __init__(self):
+        super().__init__()
+        self._A = None
+        self._n2i = None
+        self._i2n = None
+        self._dg = None
+        self._inputs= None
+        self._df_conds = None
+        self._df_exp = None
+        self._df_ptb = None
+        self._names_ptb = None
+        self._iadj_to_idf = None
+        self._has_link_perturb = None
+
+    def initialize(self,
+                   fpath,
+                   fname_network="network.sif",
+                   fname_ptb="ptb.tsv",
+                   fname_conds="conds.tsv",
+                   fname_exp="exp.tsv",
+                   inputs={}):
+
+        dpath = os.path.dirname(fpath)
+        fpath_network = os.path.join(dpath, fname_network)
+        fpath_ptb = os.path.join(dpath, fname_ptb)
+
+        A, n2i, dg = sfa.read_sif(fpath_network, as_nx=True)
+        self._A = A
+        self._n2i = n2i
+        self._dg = dg
+        self._df_conds = pd.read_table(os.path.join(dpath, fname_conds),
+                                       header=0, index_col=0)
+        self._df_exp = pd.read_table(os.path.join(dpath, fname_exp),
+                                     header=0, index_col=0)
+
+        self._inputs = inputs
+        self._df_ptb = pd.read_table(fpath_ptb, index_col=0)
+        if any(self._df_ptb.Type == 'link'):
+            self._has_link_perturb = True
+        else:
+            self._has_link_perturb = False
+
+        self._names_ptb = []
+        for i, row in enumerate(self._df_conds.iterrows()):
+            row = row[1]
+            list_name = []  # Target names
+            for target in self._df_conds.columns[row.nonzero()]:
+                list_name.append(target)
+            # end of for
+            self._names_ptb.append(list_name)
+        # end of for
+
+        # For mapping from the indices of adj. matrix to those of DataFrame
+        # (arrange the indices of adj. matrix according to df_exp.columns)
+        self._iadj_to_idf = [n2i[x] for x in self._df_exp.columns]
+
+        self._i2n = {idx: name for name, idx in n2i.items()}
+
+    # end of def
+
+    # Read-only members
+    @property
+    def A(self):  # Adjacency matrix (numpy.ndarray)
+        return self._A
+
+    @property
+    def n2i(self):  # Name to index mapping (hashable)
+        return self._n2i
+
+    @property
+    def i2n(self):  # Index to name mapping (hashable)
+        return self._i2n
+
+    @property
+    def dg(self):  # Directed graph object of NetworkX
+        return self._dg
+
+    @property  # List of perturbation targets
+    def names_ptb(self):
+        return self._names_ptb
+
+    @property  # List of values for perturbation
+    def vals_ptb(self):
+        return self._vals_ptb
+
+#    @property  # List of perturbation types
+#    def types_ptb(self):
+#        return self._types_ptb
+
+    @property
+    def iadj_to_idf(self):
+        return self._iadj_to_idf
+
+    @iadj_to_idf.setter
+    def iadj_to_idf(self, arr):
+        self._iadj_to_idf = arr
+
+    # Replaceable (assignable) members
+    @property
+    def inputs(self):  # Input conditions
+        return self._inputs
+
+    @inputs.setter
+    def inputs(self, obj_dict):
+        self._inputs = obj_dict
+
+    @property  # DataFrame of experimental conditions
+    def df_conds(self):
+        return self._df_conds
+
+    @df_conds.setter
+    def df_conds(self, df):
+        self._df_conds = df
+
+    @property  # DataFrame of experimental results
+    def df_exp(self):
+        return self._df_exp
+
+    @df_exp.setter
+    def df_exp(self, df):
+        self._df_exp = df
+
+    @property  # DataFrame of perturbation information
+    def df_ptb(self):
+        return self._df_ptb
+
+    @df_ptb.setter
+    def df_ptb(self, df):
+        self._df_ptb = df
+
+    @property
+    def has_link_perturb(self):
+        return self._has_link_perturb
+
+    @has_link_perturb.setter
+    def has_link_perturb(self, val):
+        if not isinstance(val, bool):
+            raise TypeError("has_link_perturb should be boolean.")
+        self._has_link_perturb = val
+
+# end of class Data
+
+
+class Result(sfa.utils.FrozenClass):
+
+    def __init__(self):
+        self._df_sim = None
+        self._freeze()
+
+    @property
+    def df_sim(self):
+        return self._df_sim
+
+    @df_sim.setter
+    def df_sim(self, val):
+        self._df_sim = val
+
+# end of def class Result