Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"weight" is not a key in the graph and is added by calc_root_length #24

Open
2 tasks
eberrigan opened this issue Jan 13, 2025 · 0 comments
Open
2 tasks

Comments

@eberrigan
Copy link
Collaborator

eberrigan commented Jan 13, 2025

The json file representing the root structure has the following format

{
    "directed": true,
    "multigraph": false,
    "graph": [],
    "nodes": [
        {
            "pos": [
                0,
                0
            ],
            "LR_index": null,
            "root_deg": 0,
            "id": 0
        },
        {
            "pos": [
                12.0,
                10.0
            ],
            "LR_index": null,
            "root_deg": 0,
            "id": 1
        },
    ],
    "adjacency": [
        [
            {
                "id": 1
            }
        ],
        [
            {
                "id": 2
            },
            {
                "id": 30
            }
        ],
    ]
}  

where "weight" is not a key for the edges.

  • This should be added so that future data has this key when the json file is saved from the GUI.
  • There should be backwards compatibility so that if data does not have a weight key it is added when loading the graph from the JSON.

Currently, this code only works because calc_root_length is always run on all of the roots before getting the pareto-related calcs when quantify.analyze(graph) is used. This is always the case from the GUI, but people trying to use the API will not be able to use the pareto functions modularly, and can only analyze results using quantify.analyze. This makes unit tests impossible.

The weight attribute is referenced in graph_costs which is used by pareto_front and random_tree`.

edge_length = G[current_node][child_node]["weight"]

def calc_root_len(G, nodes):
"""Return the pairwise Euclidean distance along a list of consecutive nodes."""
dist = 0
# order matters! assumes consecutive, increasing depth
for prev, current_node in zip(nodes, nodes[1:]):
segment = distance(G.nodes[prev]["pos"], G.nodes[current_node]["pos"])
dist += segment
# might as well annotate the edges while I'm here
G.edges[prev, current_node]["weight"] = segment
return dist

def analyze(G):
"""Report basic root metrics for a given graph."""
# check that graph is indeed a tree (acyclic, undirected, connected)
assert nx.is_tree(G)
# independent deep copy of G, with LRs below threshold excluded
H = copy.deepcopy(G)
# find top ("root") node
for node in H.nodes(data="pos"):
if node[1] == [0, 0]:
root_node = node[0]
# the pareto functions are hardcoded to assume node 0 is the top.
assert root_node == 0
# PR len
len_PR = calc_len_PR(H, root_node)
# print('PR length is:', len_PR)
# LR len/number
LR_info = calc_len_LRs(H)
num_LRs = len(LR_info)
lens_LRs = [x[0] for x in LR_info.values()]
angles_LRs = [x[1] for x in LR_info.values()]
# print('LR lengths are:', lens_LRs)
# print('Set point angles are:', angles_LRs)
# primary LR density
density_LRs = num_LRs / len_PR
# print('LR density is:', num_LRs/len_PR)
# Calculate the Euclidean distance between the uppermost node and the lowermost node of the primary root
uppermost_node_pos = H.nodes[root_node]["pos"]
lowermost_node_pos = find_lowermost_node_of_primary_root(H, root_node)
distance_root = calculate_distance(uppermost_node_pos, lowermost_node_pos)
results, front, randoms = pareto_calcs(H)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant