Пример #1
0
  def __call__ (self, reduced_parameter_index):
    """
    The query returns a graph which contains the poset of gene parameter indices 
    corresponding to adjusting the parameter by changing the logic parameter associated 
    with the gene being queried.
    The graph is as follows: 

    * The vertices of the graph are named according to Gene Parameter Index (gpi). 
    * There is a directed edge p -> q iff p < q and the associated logic parameters are adjacent.
    * The graph is labelled with pairs (Parameter index, Morse graph index).

    In addition the following extra structures are provided:

    * `graph.data` is a dictionary from gene parameter index to (hex code, parameter index, morse graph index)
    * `graph.mgi` is a function which accepts a gpi and returns the associated Morse graph index
    * `graph.num_inputs` is the number of network edges which are inputs to the gene associated with the query
    * `graph.num_outputs`is the number of network edges which are outputs to the gene associated with the query
    * `graph.essential` is a boolean-valued function which determines if each vertex corresponds to an essential parameter node
    """
    LogToSTDOUT("SingleGeneQuery(" + str(reduced_parameter_index) + ")")
    c = self.database.execute("select GeneParameterIndex,ParameterIndex,MorseGraphIndex from " + self.gene + " where ReducedParameterIndex=?", (str(reduced_parameter_index),))
    LogToSTDOUT("SingleGeneQuery: SQL statement executed")
    Q = { row[0] : (self.hexcodes[row[0]],  row[1], row[2]) for row in c }
    LogToSTDOUT("SingleGeneQuery: Q constructed")
    graph = self.graph.clone()
    LogToSTDOUT("SingleGeneQuery: graph constructed")
    graph.data = Q
    graph.mgi = lambda gpi : graph.data[gpi][2]
    graph.label = lambda gpi : str(graph.data[gpi][1]) + ':' + str(graph.data[gpi][2])
    graph.num_inputs = len(self.database.network.inputs(self.gene_index))
    graph.num_outputs = len(self.database.network.outputs(self.gene_index))
    graph.essential = lambda gpi : essential(graph.data[gpi][0],graph.num_inputs,graph.num_outputs)
    LogToSTDOUT("SingleGeneQuery: graph attributes emplaced")
    return graph
Пример #2
0
 def __init__(self, database):
     LogToSTDOUT("MonostableQuery :: initializing")
     self.database = database
     if not hasattr(database, 'MonostableQuery'):
         c = database.conn.cursor()
         LogToSTDOUT(
             "MonostableQuery :: select MorseGraphIndex from (select MorseGraphIndex, count(*) as StableCount from (select MorseGraphIndex,Vertex from MorseGraphVertices except select MorseGraphIndex,Source from MorseGraphEdges) group by MorseGraphIndex) where StableCount=1;"
         )
         sqlexpression = "select MorseGraphIndex from (select MorseGraphIndex, count(*) as StableCount from (select MorseGraphIndex,Vertex from MorseGraphVertices except select MorseGraphIndex,Source from MorseGraphEdges) group by MorseGraphIndex) where StableCount=1;"
         database.MonostableQuery = frozenset(
             [row[0] for row in c.execute(sqlexpression)])
     LogToSTDOUT("MonostableQuery :: constructed")
Пример #3
0
 def __init__(self, database, bounds):
     self.database = database
     LogToSTDOUT("SingleFixedPointQuery :: initializing")
     LogToSTDOUT("SingleFixedPointQuery :: calling MatchQuery")
     MatchQuery(bounds, "Matches", database)
     # Final query and print results
     c = database.conn.cursor()
     LogToSTDOUT(
         "SingleFixedPointQuery :: select MorseGraphIndex from Matches;")
     self.set_of_matches = set([
         row[0] for row in c.execute('select MorseGraphIndex from Matches;')
     ])
     #result = [row[0] for row in c.execute('select distinct ParameterIndex from Matches natural join Signatures order by ParameterIndex;')]
     LogToSTDOUT("SingleFixedPointQuery :: drop table Matches;")
     c.execute('drop table Matches')
     LogToSTDOUT("SingleFixedPointQuery :: constructed")
Пример #4
0
 def __call__(self, reduced_parameter_index):
     LogToSTDOUT("HysteresisQuery(" + str(reduced_parameter_index) +
                 ")")  # DEBUG
     searchgraph = self.GeneQuery(reduced_parameter_index)
     LogToSTDOUT("HysteresisQuery: Search Graph Constructed.")  # DEBUG
     searchgraph.matching_label = lambda v: self.matching_label(
         searchgraph.mgi(v))
     searchgraphstring = ''.join(
         [searchgraph.matching_label(v) for v in searchgraph.vertices])
     if searchgraphstring not in self.memoization_cache:
         alignment_graph = AlignmentGraph(searchgraph, self.patterngraph,
                                          self.matching_relation)
         LogToSTDOUT(
             "HysteresisQuery: Alignment Graph Constructed.")  # DEBUG
         LogToSTDOUT("HysteresisQuery: Alignment Graph has " +
                     str(len(alignment_graph.vertices)) +
                     " vertices")  # DEBUG
         LogToSTDOUT("HysteresisQuery: Alignment Graph has " +
                     str(len(alignment_graph.edges)) + " edges")  # DEBUG
         root_vertex = (0, 0)
         leaf_vertex = (len(searchgraph.vertices) - 1, 4)
         is_reachable = alignment_graph.reachable(root_vertex, leaf_vertex)
         #number_of_paths = alignment_graph.numberOfPaths(root_vertex, leaf_vertex)
         LogToSTDOUT("HysteresisQuery: Reachability computed.")  # DEBUG
         self.memoization_cache[searchgraphstring] = is_reachable
     LogToSTDOUT("HysteresisQuery: Returning.")  # DEBUG
     return self.memoization_cache[searchgraphstring]
Пример #5
0
 def __init__(self, database, gene, quiescent_bounds, proliferative_bounds):
     """
 In order to perform hysteresis queries we must first categorize each Morse graph as either 
 'Q' monostable quiescent, 'P' monostable proliferative, 'q' quiescent, 'p' proliferative, 'B' bistable, or 'O' other
 We assume the quiescent and proliferative FP states are given by disjoint bounding rectangles
 """
     LogToSTDOUT("HysteresisQuery(" + str(database.dbname) + ", " +
                 str(gene) + ")")
     self.database = database
     self.gene = gene
     # Create query object to check if morse graph indices have quiescent FP as only minimal morse node
     LogToSTDOUT("HysteresisQuery :: MonostableFixedPointQuery(" +
                 str(database.dbname) + ", " + str(quiescent_bounds) + ")")
     Q = MonostableFixedPointQuery(database, quiescent_bounds)
     # Create query object to check if morse graph indices has quiescent FP
     LogToSTDOUT("HysteresisQuery :: SingleFixedPointQuery(" +
                 str(database.dbname) + ", " + str(quiescent_bounds) + ")")
     q = SingleFixedPointQuery(database, quiescent_bounds)
     # Create query object to check if morse graph indices have proliferative FP as only minimal morse node
     LogToSTDOUT("HysteresisQuery :: MonostableFixedPointQuery(" +
                 str(database.dbname) + ", " + str(proliferative_bounds) +
                 ")")
     P = MonostableFixedPointQuery(database, proliferative_bounds)
     # Create query object to check if morse graph indices has proliferative FP
     LogToSTDOUT("HysteresisQuery :: SingleFixedPointQuery(" +
                 str(database.dbname) + ", " + str(proliferative_bounds) +
                 ")")
     p = SingleFixedPointQuery(database, proliferative_bounds)
     # Check query object to check if morse graph index has both quiescent FP and proliferative FP
     LogToSTDOUT("HysteresisQuery :: DoubleFixedPointQuery(" +
                 str(database.dbname) + ", " + str(quiescent_bounds) +
                 ", " + str(proliferative_bounds) + ")")
     B = DoubleFixedPointQuery(database, quiescent_bounds,
                               proliferative_bounds)
     # Create a labelling function which accepts a morse graph index and returns Q, P, B, p, q, or O
     # Note: case fallthrough order matters here
     self.matching_label = lambda mgi: 'Q' if Q(mgi) else ('P' if P(
         mgi) else ('B'
                    if B(mgi) else ('q'
                                    if q(mgi) else ('p'
                                                    if p(mgi) else 'O'))))
     # Create the pattern graph to represent Q -> B -> P (with self-loop on Q, B, and P)
     self.patterngraph = Graph(set([0, 1, 2, 3, 4]),
                               [(0, 0), (1, 1), (0, 1), (1, 0), (0, 2),
                                (1, 2), (2, 2), (2, 3), (2, 4), (3, 3),
                                (3, 4), (4, 4), (4, 3)])
     self.patterngraph.matching_label = lambda v: {
         0: 'Q',
         1: 'q',
         2: 'B',
         3: 'p',
         4: 'P'
     }[v]
     # Create matching relation (in this case we just check for equality of the matching labels)
     self.matching_relation = lambda label1, label2: label1 == label2
     # Create SingleGeneQuery object
     LogToSTDOUT("HysteresisQuery :: SingleGeneQuery(" +
                 str(database.dbname) + ", " + str(gene) + ")")
     self.GeneQuery = SingleGeneQuery(database, gene)
     self.memoization_cache = {}
Пример #6
0
def MatchQuery(bounds, outputtablename, database):
    # Parse the command line
    LogToSTDOUT("MatchQuery(" + str(bounds) + ", " + str(outputtablename) +
                ")")
    c = database.conn.cursor()
    expressions = buildQueryExpression(bounds, database)
    LogToSTDOUT("MatchQuery :: built expressions " + str(expressions))
    N = len(expressions)
    for i, expression in enumerate(expressions):
        oldtable = 'tmpMatches' + str(i)
        if i == 0: oldtable = "MorseGraphAnnotations"
        newtable = 'tmpMatches' + str(i + 1)
        if i == N - 1: newtable = outputtablename
        sql_string = 'create temp table ' + newtable + ' as select * from ' + oldtable + ' where ' + expression + ';'
        LogToSTDOUT("MatchQuery :: " + sql_string)
        c.execute(sql_string)
        if i > 0: c.execute('drop table ' + oldtable)
    LogToSTDOUT("MatchQuery :: constructed")
Пример #7
0
    def __init__(self, database, gene):
        LogToSTDOUT("SingleGeneQuery(" + str(database.dbname) + ", " +
                    str(gene) + ")")
        self.database = database
        self.gene = gene
        # "gene_index" gives the integer index used in the representation
        self.gene_index = self.database.network.index(self.gene)

        # num_gene_param is the size of the factor graph associated with "gene"
        self.num_gene_param = database.indexing_place_bases[self.gene_index]
        # num_reduced_param is the product of the sizes of all remaining factor graphs, and reorderings of all genes (including "gene")
        self.num_reduced_param = database.parametergraph.size(
        ) // self.num_gene_param

        # Create factor graph
        # TODO: The following algorithm for creating a factor graph takes O(NM^2) time, where N is length of hexcodes and M is size of factorgraph.
        #       An O(NM) algorithm is possible (based on looping through codewords and trying out each promotion, using a hash table)
        #       Implement this.
        self.hexcodes = self.database.parametergraph.factorgraph(
            self.gene_index)
        vertices = set(range(0, len(self.hexcodes)))
        edges = [(gpi1, gpi2) for gpi1 in vertices for gpi2 in vertices
                 if isAdjacentHexcode(self.hexcodes[gpi1], self.hexcodes[gpi2])
                 ]
        self.graph = Graph(vertices, edges)

        LogToSTDOUT("SingleGeneQuery: FactorGraph generated")

        if not hasattr(database, 'SingleGeneQuery'):
            LogToSTDOUT(
                "SingleGeneQuery: SingleGeneQuery attribute missing from python database object."
            )
            database.SingleGeneQuery = set()
            # For single-gene manipulations, we convert from parameter index to (reduced parameter index, gene parameter index)
            # To recover the parameter index from the reduced parameter index, we insert a "digit":
            database.full_parameter_index = lambda rpi, gpi, gene_index: rpi % database.indexing_place_values[
                gene_index] + gpi * database.indexing_place_values[
                    gene_index] + (rpi // database.indexing_place_values[
                        gene_index]) * database.indexing_place_values[
                            gene_index + 1]
            database.reduced_parameter_index = lambda pi, gene_index: (
                pi % database.indexing_place_values[gene_index] +
                (pi // database.indexing_place_values[gene_index + 1]
                 ) * database.indexing_place_values[gene_index],
                (pi // database.indexing_place_values[gene_index]
                 ) % database.indexing_place_bases[gene_index])

        LogToSTDOUT("SingleGeneQuery: SingleGeneQuery attributes created.")

        if gene not in database.SingleGeneQuery:
            LogToSTDOUT(
                "SingleGeneQuery: database structure unaware of gene " +
                str(gene))
            # Sanitize "gene":
            if gene not in database.names:
                raise NameError(gene +
                                " is not the name of a node in the network")

            LogToSTDOUT("SingleGeneQuery: sanitized " + str(gene))
            # Now we scan the database and create a new table we can do single gene poset queries with
            c = database.conn.cursor()
            # c.execute("drop table if exists " + gene) # gene is sanitized
            # Check if table exists
            LogToSTDOUT("SingleGeneQuery: cursor constructed ")

            c.execute(
                "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='"
                + gene + "';")
            LogToSTDOUT("SingleGeneQuery: checked for table")

            table_exists = c.fetchone()[0]
            if not table_exists:
                LogToSTDOUT("SingleGeneQuery: table did not exist")
                c.execute(
                    "create table " + gene +
                    " (ReducedParameterIndex INTEGER, GeneParameterIndex INTEGER, ParameterIndex INTEGER, MorseGraphIndex INTEGER)"
                )
                LogToSTDOUT("SingleGeneQuery: created table")

                # # old method -- loads whole table into memory
                # values = [ self.reduced_parameter_index(row[0], self.gene_index) + row for row in c.execute("select * from Signatures")]
                # c.executemany('INSERT INTO ' + gene + ' VALUES (?,?,?,?)', values )

                # new method -- a generator that uses fetchmany to keep memory usage down
                # default value arraysize=10000 was chosen based on limited testing. No improvement seen at 50000 or 100000 on a 13M parameter db. Worse performance at arraysize=1000.
                def valuegenerator(cursor, arraysize=10000):
                    while True:
                        rows = cursor.fetchmany(arraysize)
                        if not rows:
                            break
                        yield [
                            database.reduced_parameter_index(
                                row[0], self.gene_index) + row for row in rows
                        ]

                c2 = database.conn.cursor(
                )  # need a second cursor to keep the place in the iteration as updates to the table occur
                c2.execute("select * from Signatures")
                LogToSTDOUT(
                    "SingleGeneQuery: executed select statement on signatures")
                for values in valuegenerator(c2):
                    c.executemany('INSERT INTO ' + gene + ' VALUES (?,?,?,?)',
                                  values)
                LogToSTDOUT("SingleGeneQuery: inserted values")
                c2.close()
                LogToSTDOUT("SingleGeneQuery: closed cursor")
                c.execute('create index ' + gene + '1 on ' + gene +
                          ' (ReducedParameterIndex, GeneParameterIndex)'
                          )  # gene is sanitized
                LogToSTDOUT("SingleGeneQuery: created index")
                database.conn.commit()
                LogToSTDOUT("SingleGeneQuery: committed database transaction")
            database.SingleGeneQuery.add(gene)
            LogToSTDOUT(
                "SingleGeneQuery: added gene to python database object.")
        LogToSTDOUT("SingleGeneQuery: constructed")
Пример #8
0
 def __init__(self, database, bounds):
   LogToSTDOUT("MonostableFixedPointQuery :: initializing")
   self.set_of_matches = SingleFixedPointQuery(database,bounds).matches() & MonostableQuery(database).matches()
   LogToSTDOUT("MonostableFixedPointQuery :: constructed")