class Network

Attributes

association_values[RW]
control_connections[RW]

Public Class Methods

new(layers) click to toggle source

BASIC METHODS

# File lib/NetAnalyzer/network.rb, line 13
def initialize(layers)
        @nodes = {} 
        @edges = {}
        @adjacency_matrices = {}
        @layers = layers
        @association_values = {}
        @control_connections = {}
end

Public Instance Methods

add_edge(nodeID1, nodeID2) click to toggle source
# File lib/NetAnalyzer/network.rb, line 26
def add_edge(nodeID1, nodeID2)
        query_edge(nodeID1, nodeID2)
        query_edge(nodeID2, nodeID1)
end
add_nested_record(hash, node1, node2, val) click to toggle source
# File lib/NetAnalyzer/network.rb, line 298
def add_nested_record(hash, node1, node2, val)
        query_node1 = hash[node1]
        if query_node1.nil?
                hash[node1] = {node2 => val}
        else
                query_node1[node2] = val
        end
end
add_node(nodeID, nodeType = 0) click to toggle source
# File lib/NetAnalyzer/network.rb, line 22
def add_node(nodeID, nodeType = 0)
        @nodes[nodeID] = Node.new(nodeID, nodeType)
end
add_record(hash, node1, node2) click to toggle source
# File lib/NetAnalyzer/network.rb, line 289
def add_record(hash, node1, node2)
        query = hash[node1]
        if query.nil?
                hash[node1] = [node2]
        else
                query << node2
        end
end
clean_autorelations_on_association_values() click to toggle source
# File lib/NetAnalyzer/network.rb, line 142
def clean_autorelations_on_association_values
        @association_values.each do |meth, values|
                values.select!{|relation| @nodes[relation[0]].type != @nodes[relation[1]].type}
        end
end
generate_adjacency_matrix(layerA, layerB) click to toggle source
# File lib/NetAnalyzer/network.rb, line 123
def generate_adjacency_matrix(layerA, layerB)
        layerAidNodes = @nodes.select{|id, node| node.type == layerA}.keys
        layerBidNodes = @nodes.select{|id, node| node.type == layerB}.keys
        adjacency_matrix = []
        layerAidNodes.each do |nodeA|
                layerBidNodes.each do |nodeB|
                        if @edges[nodeB].include?(nodeA)
                                adjacency_matrix << 1
                        else
                                adjacency_matrix << 0
                        end
                end
        end
        matrix = NMatrix.new([layerAidNodes.length, layerBidNodes.length], adjacency_matrix)
        all_info_matrix = [matrix, layerAidNodes, layerBidNodes]
        @adjacency_matrices[[layerA, layerB]] = all_info_matrix
        return all_info_matrix
end
get_all_intersections() click to toggle source
# File lib/NetAnalyzer/network.rb, line 71
def get_all_intersections
        intersection_lengths = []
        get_all_pairs do |node1, node2|
                intersection_lengths << intersection(node1, node2).length
        end
        return intersection_lengths
end
get_all_pairs(args = {}) { |node1, node2| ... } click to toggle source
# File lib/NetAnalyzer/network.rb, line 79
def get_all_pairs(args = {})
        default = {:meth => :all, :layers => :all}
        args = default.merge(args)
        if args[:layers] == :all
                nodeIDs = @nodes.keys
        else
                nodeIDs = []
                args[:layers].each do |layer|
                        nodeIDs.concat(@nodes.select{|id, node| node.type == layer}.keys)
                end
        end

        if args[:meth] == :all
                while !nodeIDs.empty?
                        node1 = nodeIDs.shift
                        nodeIDs.each do |node2|
                                yield(node1, node2)
                        end
                end
        #elsif args[:meth] == :conn
                
        end
end
get_association_by_transference_resources(firstPairLayers, secondPairLayers, lambda_value1 = 0.5, lambda_value2 = 0.5) click to toggle source

association methods adjacency matrix based

# File lib/NetAnalyzer/network.rb, line 175
def get_association_by_transference_resources(firstPairLayers, secondPairLayers, lambda_value1 = 0.5, lambda_value2 = 0.5)
        matrix1 = @adjacency_matrices[firstPairLayers].first
        rowIds = @adjacency_matrices[firstPairLayers][1]
        matrix2 = @adjacency_matrices[secondPairLayers].first
        colIds =  @adjacency_matrices[secondPairLayers][2]
        m1rowNumber = matrix1.rows
        m1colNumber = matrix1.cols
        m2rowNumber = matrix2.rows
        m2colNumber = matrix2.cols
        #puts m1rowNumber, m1colNumber, m2rowNumber, m2colNumber
        matrix1Weight = graphWeights(m1colNumber, m1rowNumber, matrix1.transpose, lambda_value1)
        matrix2Weight = graphWeights(m2colNumber, m2rowNumber, matrix2.transpose, lambda_value2)
        matrixWeightProduct = matrix1Weight.dot(matrix2.dot(matrix2Weight))
        finalMatrix = matrix1.dot(matrixWeightProduct)
        relations = nmatrix2relations(finalMatrix, rowIds, colIds)
        @association_values[:transference] = relations
        return relations
end
get_association_values(layers, base_layer, meth) click to toggle source

ASSOCIATION METHODS

# File lib/NetAnalyzer/network.rb, line 150
def get_association_values(layers, base_layer, meth)
        relations = [] #node A, node B, val
        if meth == :jaccard #all networks
                relations = get_jaccard_association(layers, base_layer)
        elsif meth == :simpson #all networks
                relations = get_simpson_association(layers, base_layer)
        elsif meth == :geometric #all networks
                relations = get_geometric_associations(layers, base_layer)
        elsif meth == :cosine #all networks
                relations = get_cosine_associations(layers, base_layer)
        elsif meth == :pcc #all networks
                relations = get_pcc_associations(layers, base_layer)
        elsif meth == :hypergeometric #all networks
                relations = get_hypergeometric_associations(layers, base_layer)
        elsif meth == :csi #all networks
                relations = get_csi_associations(layers, base_layer)
        elsif meth == :transference #tripartite networks
                relations = get_association_by_transference_resources(layers, base_layer)
        end
        return relations
end
get_associations(layers, base_layer) { |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2| ... } click to toggle source

association methods node pairs based

# File lib/NetAnalyzer/network.rb, line 197
def get_associations(layers, base_layer) # BASE METHOD
        relations = []
        get_all_pairs(layers: layers) do |node1, node2|
                associatedIDs_node1 = @edges[node1].map{|id| @nodes[id]}.select{|node| node.type == base_layer}.map{|node| node.id}
                associatedIDs_node2 = @edges[node2].map{|id| @nodes[id]}.select{|node| node.type == base_layer}.map{|node| node.id}
                intersectedIDs = associatedIDs_node1 & associatedIDs_node2
                associationValue = yield(associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2)
                relations << [node1, node2, associationValue]  
        end
        return relations
end
get_cosine_associations(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 238
def get_cosine_associations(layers, base_layer)
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|
                productLength = Math.sqrt(associatedIDs_node1.length * associatedIDs_node2.length)
                cosineValue = intersectedIDs.length/productLength
        end
        @association_values[:cosine] = relations
        return relations
end
get_csi_associations(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 308
def get_csi_associations(layers, base_layer)
        pcc_relations = get_pcc_associations(layers, base_layer)
        clean_autorelations_on_association_values if layers.length > 1
        nx = get_nodes_layer(layers).length
        pcc_vals = {}
        node_rels = {}
        pcc_relations.each do |node1, node2, assoc_index|
                add_nested_record(pcc_vals, node1, node2, assoc_index.abs)
                add_nested_record(pcc_vals, node2, node1, assoc_index.abs)
                add_record(node_rels, node1, node2)
                add_record(node_rels, node2, node1)
        end
        relations = []
        pcc_relations.each do |node1, node2 ,assoc_index|
                pccAB = assoc_index - 0.05
                valid_nodes = 0
                node_rels[node1].each do |node|
                        valid_nodes += 1 if pcc_vals[node1][node] >= pccAB
                end
                node_rels[node2].each do |node|
                        valid_nodes += 1 if pcc_vals[node2][node] >= pccAB
                end
                csiValue = 1 - (valid_nodes-1).fdiv(nx) 
                # valid_nodes-1 is done due to the connection node1-node2 is counted twice (one for each loop)
                relations << [node1, node2, csiValue]
        end
        @association_values[:csi] = relations
        return relations
end
get_edge_number() click to toggle source
# File lib/NetAnalyzer/network.rb, line 52
def get_edge_number
        node_connections = @edges.values.map{|connections| connections.length}.inject(0){|sum, n| sum + n}
        return node_connections/2
end
get_geometric_associations(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 227
def get_geometric_associations(layers, base_layer)
        #wang 2016 method
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|  
                intersectedIDs = intersectedIDs.length**2
                productLength = Math.sqrt(associatedIDs_node1.length * associatedIDs_node2.length)
                geometricValue = intersectedIDs.to_f/productLength
        end
        @association_values[:geometric] = relations
        return relations
end
get_hypergeometric_associations(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 262
def get_hypergeometric_associations(layers, base_layer)
        ny = get_nodes_layer([base_layer]).length
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|
                minLength = [associatedIDs_node1.length, associatedIDs_node2.length].min
                intersection_lengths = intersectedIDs.length
                sum = 0
                if intersection_lengths > 0
                        nA = associatedIDs_node1.length
                        nB = associatedIDs_node2.length
                        #Using index from A layer proyected to B
                        hyper_denom = binom(ny, nB)
                        (intersection_lengths..minLength).each do |i|
                                binom_product = binom(nA, i) * binom(ny - nA, nB - i)
                                sum += binom_product.fdiv(hyper_denom)
                        end
                end
                if sum == 0
                        hypergeometricValue = 0
                else
                        hypergeometricValue = -Math.log10(sum)
                end
                hypergeometricValue
        end
        @association_values[:hypergeometric] = relations
        return relations
end
get_jaccard_association(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 209
def get_jaccard_association(layers, base_layer)
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|
                unionIDS = associatedIDs_node1 | associatedIDs_node2
                jaccValue = intersectedIDs.length.to_f/unionIDS.length               
        end
        @association_values[:jaccard] = relations
        return relations
end
get_nodes_layer(layers) click to toggle source
# File lib/NetAnalyzer/network.rb, line 103
def get_nodes_layer(layers)
        #for creating ny value in hypergeometric and pcc index
        nodes = []
        layers.each do |layer|
                nodes.concat(@nodes.select{|nodeId, node| node.type == layer}.values)
        end
        return nodes
end
get_pcc_associations(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 247
def get_pcc_associations(layers, base_layer)
        #for Ny calcule use get_nodes_layer
        ny = get_nodes_layer([base_layer]).length
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|
                intersProd = intersectedIDs.length * ny
                nodesProd = associatedIDs_node1.length * associatedIDs_node2.length
                nodesSubs = intersProd - nodesProd
                nodesAInNetwork = ny - associatedIDs_node1.length
                nodesBInNetwork = ny - associatedIDs_node2.length
                pccValue = nodesSubs.to_f / Math.sqrt(nodesProd * nodesAInNetwork * nodesBInNetwork)
        end
        @association_values[:pcc] = relations
        return relations
end
get_pred_rec(meth, cut_number = 100, top_number = 10000) click to toggle source

Pandey 2007, Association Analysis-based Transformations for Protein Interaction Networks: A Function Prediction Case Study

# File lib/NetAnalyzer/network.rb, line 381
def get_pred_rec(meth, cut_number = 100, top_number = 10000)
        performance = [] #cut, pred, rec
        preds, limits = load_prediction(@association_values[meth])
        cuts = get_cuts(limits, cut_number)
        cuts.each do |cut|
                prec, rec = pred_rec(preds, cut, top_number)
                performance << [cut, prec, rec]
        end
        return performance
end
get_simpson_association(layers, base_layer) click to toggle source
# File lib/NetAnalyzer/network.rb, line 218
def get_simpson_association(layers, base_layer)
        relations = get_associations(layers, base_layer) do |associatedIDs_node1, associatedIDs_node2, intersectedIDs, node1, node2|
                minLength = [associatedIDs_node1.length, associatedIDs_node2.length].min
                simpsonValue = intersectedIDs.length.to_f/minLength
        end
        @association_values[:simpson] = relations
        return relations
end
intersection(node1, node2) click to toggle source
# File lib/NetAnalyzer/network.rb, line 112
def intersection(node1, node2)
        shared_nodes = []
        associatedIDs_node1 = @edges[node1]
        associatedIDs_node2 = @edges[node2]
        intersectedIDs = associatedIDs_node1 & associatedIDs_node2
        intersectedIDs.each do |id|
                shared_nodes << @nodes[id]
        end
        return shared_nodes
end
load_control(ref_array) click to toggle source

PERFORMANCE METHODS

# File lib/NetAnalyzer/network.rb, line 341
def load_control(ref_array)
        control = {}
        ref_array.each do |node1, node2|
                if node2 != '-'
                        query = control[node1]
                        if query.nil?
                                control[node1] = [node2]
                        else
                                query << node2
                        end
                end
        end
        @control_connections = control
        return control
end
load_network_by_pairs(file, layers, split_character="\t") click to toggle source
# File lib/NetAnalyzer/network.rb, line 40
def load_network_by_pairs(file, layers, split_character="\t")
        File.open(file).each("\n") do |line|
                line.chomp!
                pair = line.split(split_character)
                node1 = pair[0]
                node2 = pair[1]
                add_node(node1, set_layer(layers, node1))
                add_node(node2, set_layer(layers, node2))
                add_edge(node1, node2)       
        end
end
load_prediction(pairs_array) click to toggle source
# File lib/NetAnalyzer/network.rb, line 357
def load_prediction(pairs_array)
        pred = {}
        min = nil
        max = nil
        pairs_array.each do |key, label, score|
                query = pred[key]
                if !min.nil? && !max.nil?
                        min = score if score < min
                        max = score if score > max
                else
                        min = score; max = score
                end
                if query.nil?
                        pred[key] = [[label], [score]]
                else
                        query.first << label
                        query.last << score
                end
        end
        return pred, [min, max]
end
plot(output_filename, layout="dot") click to toggle source
# File lib/NetAnalyzer/network.rb, line 57
def plot(output_filename, layout="dot")                
        roboWrite = File.open(output_filename, 'w')
        roboWrite.puts "digraph g {"
        @edges.each do |nodeID, associatedIDs|
                associatedIDs.each do |associatedID|
                        roboWrite.puts "\"#{nodeID}\"->\"#{associatedID}\";"
                end
        end
        roboWrite.puts "}"
        roboWrite.close
        cmd = "#{layout} -Tpng #{output_filename} -o #{output_filename}.png"
        system(cmd)
end
pred_rec(preds, cut, top) click to toggle source
# File lib/NetAnalyzer/network.rb, line 392
def pred_rec(preds, cut, top)
        predicted_labels = 0 #m
        true_labels = 0 #n
        common_labels = 0 # k
        @control_connections.each do |key, c_labels|
                true_labels += c_labels.length #n
                pred_info = preds[key]
                if !pred_info.nil?
                        labels, scores = pred_info
                        reliable_labels = get_reliable_labels(labels, scores, cut, top)
                        predicted_labels += reliable_labels.length #m
                        common_labels += (c_labels & reliable_labels).length #k
                end
        end
        #puts "cut: #{cut} trueL: #{true_labels} predL: #{predicted_labels} commL: #{common_labels}"
        prec = common_labels.to_f/predicted_labels
        rec = common_labels.to_f/true_labels
        prec = 0.0 if prec.nan?
        rec = 0.0 if rec.nan?
        return prec, rec
end
query_edge(nodeA, nodeB) click to toggle source
# File lib/NetAnalyzer/network.rb, line 31
def query_edge(nodeA, nodeB)
        query = @edges[nodeA]
        if query.nil?
                @edges[nodeA] = [nodeB]
        else
                query << nodeB
        end
end

Private Instance Methods

binom(n,k) click to toggle source
# File lib/NetAnalyzer/network.rb, line 480
def binom(n,k)
        if k > 0 && k < n
                res = (1+n-k..n).inject(:*)/(1..k).inject(:*)
        else
                res = 1
        end
end
get_cuts(limits, n_cuts) click to toggle source
# File lib/NetAnalyzer/network.rb, line 435
def get_cuts(limits, n_cuts)
        cuts = []
        range = (limits.last - limits.first).abs.fdiv(n_cuts)
        range = BigDecimal(range, 10)
        cut = limits.first
        (n_cuts + 1).times do |n|
                cuts << (cut + n * range).to_f
        end
        return cuts
end
get_reliable_labels(labels, scores, cut, top) click to toggle source
# File lib/NetAnalyzer/network.rb, line 446
def get_reliable_labels(labels, scores, cut, top)
        reliable_labels = []
        scores.each_with_index do |score, i|
                reliable_labels << [labels[i], score] if score >= cut
        end
        reliable_labels = reliable_labels.sort!{|l1,l2| l2.last <=> l1.last}[0..top-1].map{|pred| pred.first}
        return reliable_labels
end
graphWeights(rowsNumber, colsNumber, inputMatrix, lambdaValue = 0.5) click to toggle source
# File lib/NetAnalyzer/network.rb, line 455
def graphWeights (rowsNumber, colsNumber, inputMatrix, lambdaValue = 0.5)
        invMatrix = inputMatrix.sum(0).map{|e| 1.0/ e}
       diagonalColSums = NMatrix.diag(invMatrix)
       rowsSums = inputMatrix.sum(1).to_flat_a
       ky = NMatrix.new([rowsNumber, rowsNumber], rowsSums).map{|e| e ** lambdaValue }      
       invertLambdaVal = (1 - lambdaValue)
       kx = NMatrix.new([rowsNumber, rowsNumber], rowsSums).transpose.map{|e| e ** invertLambdaVal } 
       nx = (ky * kx).map{|e| 1.0/ e}
       weigth = (inputMatrix.dot(diagonalColSums)).transpose
       weigth = inputMatrix.dot(weigth)
       weigth = nx * weigth
       return weigth
end
nmatrix2relations(finalMatrix, rowIds, colIds) click to toggle source
# File lib/NetAnalyzer/network.rb, line 469
def nmatrix2relations(finalMatrix, rowIds, colIds)
        relations = []
        rowIds.each_with_index do |rowId, rowPos|
                colIds.each_with_index do |colId, colPos|
                        associationValue = finalMatrix[rowPos, colPos]
                        relations << [rowId, colId, associationValue]
                end
        end
        return relations
end
set_layer(layer_definitions, node_name) click to toggle source

AUXILIAR METHODS

# File lib/NetAnalyzer/network.rb, line 420
def set_layer(layer_definitions, node_name)
        layer = nil
        if layer_definitions.length > 1
                layer_definitions.each do |layer_name, regexp|
                        if node_name =~ regexp
                                layer = layer_name
                                break
                        end
                end
        else
                layer = layer_definitions.first.first
        end
        return layer
end