Closed biphy closed 9 months ago
Oh this is a great function to have!
I'm copying here the functions that I removed from my PR in case they are useful:
"""
single_addition_loop_length_and_type(connectivity::AbstractMatrix, loop_start::AbstractVector)
Returns the length and type of a feedback loop given its start node for a single addition to a negative-feedback-only network.
# Arguments (Required)
- `connectivity::AbstractMatrix`: Connectivity matrix of a network
- `loop_start::AbstractVector`: Vector containing the coordinates of the start node of a feedback loop
# Returns
- `loop_properties::DataFrame`: DataFrame containing the length and type of a feedback loop
"""
function calculate_loop_length_and_type(connectivity::AbstractMatrix, loop_start::AbstractVector)
nodes = size(connectivity, 1)
feedback_sign = connectivity[loop_start...]
loop_length = 1
loop_type = "unknown"
initial_node = loop_start[1]
current_node = loop_start[2]
next_node = loop_start[2]
# Backtrace the loop
iterations = 0
while next_node != initial_node
current_node = next_node
next_node = findall(connectivity[next_node, :] .!= 0)[1]
feedback_sign *= connectivity[current_node, next_node]
loop_length += 1
iterations += 1
if iterations > nodes
error("Loop length is larger than the number of nodes")
end
end
if feedback_sign == 1
loop_type = "positive"
elseif feedback_sign == -1
loop_type = "negative"
end
loop_properties = DataFrame(length = loop_length, type = loop_type)
return loop_properties
end
"""
classify_single_addition(reference_connectivity::AbstractMatrix, one_added_connectivity::AbstractMatrix)
Returns the coherence and feedback loop type of a single addition to a reference network.
# Arguments (Required)
- `reference_connectivity::AbstractMatrix`: Connectivity matrix used as a reference for comparison
- `one_added_connectivity::AbstractMatrix`: Connectivity matrix with one addition with respect to the reference connectivity
# Returns
- `addition_properties::DataFrame`: DataFrame containing the coherence and feedback loop type of a single addition to a reference network
"""
function classify_single_addition(reference_connectivity::AbstractMatrix, one_added_connectivity::AbstractMatrix)
# Check that the reference connectivity is a negative feedback network
if !is_negative_feedback_network(reference_connectivity)
error("Reference connectivity should be a negative feedback network")
end
added_edge_indices = findall(reference_connectivity .!= one_added_connectivity)[1]
loop_start = [added_edge_indices[1], added_edge_indices[2]]
loop_properties = calculate_loop_length_and_type(one_added_connectivity, loop_start)
node_inputs = one_added_connectivity[added_edge_indices[1], :]
node_coherence = calculate_node_coherence(node_inputs)
if node_coherence.coherent[1] == 1 && node_coherence.incoherent[1] == 0
loop_coherence = "coherent"
elseif node_coherence.incoherent[1] == 1 && node_coherence.coherent[1] == 0
loop_coherence = "incoherent"
else
loop_coherence = "unknown"
end
addition_properties = DataFrame(loop_coherence = loop_coherence,
loop_length = loop_properties.length,
loop_type = loop_properties.type)
return addition_properties
end
and the tests I wrote for them
# Test calculate_loop_length_and_type
connectivity = [0 0 0 1 -1;-1 0 0 0 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0]
loop_start = [1, 4]
loop_properties = calculate_loop_length_and_type(connectivity, loop_start)
@test loop_properties.length[1] == 4
@test loop_properties.type[1] == "negative"
connectivity = [1 0 0 0 -1;-1 0 0 0 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0]
loop_start = [1, 1]
loop_properties = calculate_loop_length_and_type(connectivity, loop_start)
@test loop_properties.length[1] == 1
@test loop_properties.type[1] == "positive"
connectivity = [0 0 0 0 -1;-1 0 0 1 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0]
loop_start = [2, 4]
loop_properties = calculate_loop_length_and_type(connectivity, loop_start)
@test loop_properties.length[1] == 3
@test loop_properties.type[1] == "positive"
connectivity = [0 0 0 0 -1;-1 0 0 0 0;0 -1 0 1 0;0 0 -1 0 0;0 0 0 -1 0]
loop_start = [3, 4]
loop_properties = calculate_loop_length_and_type(connectivity, loop_start)
@test loop_properties.length[1] == 2
@test loop_properties.type[1] == "negative"
connectivity = [0 0 0 0 -1;-1 0 0 0 0;0 -1 0 -1 0;0 0 -1 0 0;0 0 0 -1 0]
loop_start = [3, 4]
loop_properties = calculate_loop_length_and_type(connectivity, loop_start)
@test loop_properties.length[1] == 2
@test loop_properties.type[1] == "positive"
# Test classify_single_addition
reference_connectivity = [0 0 -1;-1 0 0;0 -1 0]
one_add_connectivity = [1 0 -1;-1 0 0;0 -1 0]
addition_properties = classify_single_addition(reference_connectivity, one_add_connectivity)
@test addition_properties.loop_type[1] == "positive"
@test addition_properties.loop_length[1] == 1
@test addition_properties.loop_coherence[1] == "incoherent"
one_add_connectivity = [-1 0 -1;-1 0 0;0 -1 0]
addition_properties = classify_single_addition(reference_connectivity, one_add_connectivity)
@test addition_properties.loop_type[1] == "negative"
@test addition_properties.loop_length[1] == 1
@test addition_properties.loop_coherence[1] == "coherent"
one_add_connectivity = [0 1 -1;-1 0 0;0 -1 0]
addition_properties = classify_single_addition(reference_connectivity, one_add_connectivity)
@test addition_properties.loop_type[1] == "negative"
@test addition_properties.loop_length[1] == 2
@test addition_properties.loop_coherence[1] == "incoherent"
one_add_connectivity = [0 -1 -1;-1 0 0;0 -1 0]
addition_properties = classify_single_addition(reference_connectivity, one_add_connectivity)
@test addition_properties.loop_type[1] == "positive"
@test addition_properties.loop_length[1] == 2
@test addition_properties.loop_coherence[1] == "coherent"
reference_connectivity = [0 0 0 0 -1;-1 0 0 0 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0]
one_add_connectivity = [0 0 0 1 -1;-1 0 0 0 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0]
addition_properties = classify_single_addition(reference_connectivity, one_add_connectivity)
@test addition_properties.loop_type[1] == "negative"
@test addition_properties.loop_length[1] == 4
@test addition_properties.loop_coherence[1] == "incoherent"
# catch error
reference_connectivity_not_nf = [0 0 -1;-1 0 0; 0 -1 1]
one_add_connectivity = [1 0 -1;-1 0 0;0 -1 0]
@test_throws ErrorException classify_single_addition(reference_connectivity_not_nf, one_add_connectivity)
A function to find all cycles from a given connectivity matrix is added.