/usr/share/pyshared/pebl/posterior.py is in python-pebl 1.0.2-2build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | """Class for representing posterior distribution."""
import math
from copy import deepcopy
from itertools import izip
import pydot
import numpy as N
from pebl import network
from pebl.util import *
class Posterior(object):
"""Class for representing posterior distribution.
Except for trivial cases, we can only have an estimated posterior
distribution. It is usually constructed as a list of the top N networks
found during a search of the space of networks.
The pebl posterior object supports a list-like interface. So, given a
posterior object post, one can do the following:
* Access the top-scoring network: post[0]
* Access the top 10 networks as a new posterior object: post[0:10]
* Calculate entropy of distribution: post.entropy
* Iterate through networks: for net in post: print net.score
Note: a posterior object is immutable. That is, you cannot add and remove
networks once it is created. See result.Result for a mutable container for
networks.
"""
def __init__(self, nodes, adjacency_matrices, scores, sortedscores=False):
"""Creates a posterior object.
adjacency_matrices and scores can be lists or numpy arrays.
If sorted is True, adjacency_matrices and scores should be sorted in
descending order of score.
"""
if not sortedscores:
mycmp = lambda x,y: cmp(x[1],y[1])
adjmat_and_scores = sorted(zip(adjacency_matrices, scores),
cmp=mycmp, reverse=True)
adjacency_matrices, scores = unzip(adjmat_and_scores)
self.adjacency_matrices = N.array(adjacency_matrices)
self.scores = N.array(scores)
self.nodes = nodes
#
# Public interface
#
def consensus_network(self, threshold=.3):
"""Return a consensus network with the given threshold."""
features = self.consensus_matrix
features[features >= threshold] = 1
features[features < threshold] = 0
features = features.astype(bool)
return network.Network(self.nodes, features)
@property
def entropy(self):
"""The information entropy of the posterior distribution."""
# entropy = -scores*log(scores)
# but since scores are in log,
# entropy = -exp(scores)*scores
lscores = rescale_logvalues(self.scores)
return -N.sum(N.exp(lscores)*lscores)
@property
def consensus_matrix(self):
norm_scores = normalize(N.exp(rescale_logvalues(self.scores)))
return sum(n*s for n,s in zip(self.adjacency_matrices, norm_scores))
#
# Special interfaces
#
def __iter__(self):
"""Iterate over the networks in the posterior in sorted order."""
for adjmat,score in zip(self.adjacency_matrices, self.scores):
net = network.Network(self.nodes, adjmat)
net.score = score
yield net
def __getitem__(self, key):
"""Retrieve a specific network (and score) from the posterior."""
if isinstance(key, slice):
return self.__getslice__(self, key.start, key.stop)
net = network.Network(self.nodes, self.adjacency_matrices[key])
net.score = self.scores[key]
return net
def __getslice__(self, i, j):
"""Retrieve a subset (as a new posterior object) of the networks."""
return Posterior(
self.nodes,
self.adjacency_matrices[i:j], self.scores[i:j]
)
def __len__(self):
"""Return the number of networks in this posterior distribution."""
return len(self.scores)
#
# Factory functions
#
def from_sorted_scored_networks(nodes, networks):
"""Create a posterior object from a list of sorted, scored networks.
networks should be sorted in descending order.
"""
return Posterior(
nodes,
[n.edges.adjacency_matrix for n in networks],
[n.score for n in networks]
)
|