Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 31 additions & 15 deletions skm_tools/ckn_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ def filter_ckn_edges(g, keep_edge_ranks, remove_isolates=True):
if isinstance(keep_edge_ranks, int):
keep_edge_ranks = [keep_edge_ranks]

to_remove_ranks = []
for r in ckn_ranks:
if not (r in keep_edge_ranks):
to_remove_ranks.append(r)

to_remove_ranks = [r for r in ckn_ranks if r not in keep_edge_ranks]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function filter_ckn_edges refactored with the following changes:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought (llm): The refactoring to a list comprehension is cleaner, but consider if 'keep_edge_ranks' would benefit from being a set for performance reasons similar to the previous comment on 'skip_nodes'.

to_remove = []
for r in to_remove_ranks:
to_remove += [(u,v) for u, v, d in g.edges(data=True,) if d["rank"]==r]
Expand Down Expand Up @@ -62,23 +58,38 @@ def filter_ckn_nodes(

if species:
no_species = [
n for n, data in g.nodes(data=True) if not (
data['species'] in species
)
n
for n, data in g.nodes(data=True)
if data['species'] not in species
]
to_remove.update(no_species)
reasons = {**reasons, **{n:"wrong species" for n in no_species if not n in reasons}}
reasons = reasons | {
n: "wrong species" for n in no_species if n not in reasons
}

if node_types:
# nodes not in keep_types
wrong_type = [n for n, data in g.nodes(data=True) if not (data['node_type'] in node_types)]
wrong_type = [
n
for n, data in g.nodes(data=True)
if data['node_type'] not in node_types
]
to_remove.update(wrong_type)
reasons = {**reasons, **{n:"wrong node type" for n in wrong_type if not n in reasons}}
reasons = reasons | {
n: "wrong node type" for n in wrong_type if n not in reasons
}

if tissues:
wrong_tissue = [n for n, data in g.nodes(data=True) if ( not data['tissue'] ) or ( not (len([aa for aa in data['tissue'] if aa in tissues])>0) )]
wrong_tissue = [
n
for n, data in g.nodes(data=True)
if not data['tissue']
or not [aa for aa in data['tissue'] if aa in tissues]
]
to_remove.update(wrong_tissue)
reasons = {**reasons, **{n:"wrong tissue type" for n in wrong_tissue if not n in reasons}}
reasons = reasons | {
n: "wrong tissue type" for n in wrong_tissue if n not in reasons
}
Comment on lines -65 to +92

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function filter_ckn_nodes refactored with the following changes:



# now remove complexes that contain any nodes to be removed entities
Expand All @@ -94,9 +105,14 @@ def complex_to_remove(x):
for n in x.split("|"):
if n in as_components:
return True

complex_component_missing = [n for n in g.nodes() if complex_to_remove(n)]
to_remove.update(complex_component_missing)
reasons = {**reasons, **{n:"complex component removed" for n in complex_component_missing if not n in reasons}}
reasons = reasons | {
n: "complex component removed"
for n in complex_component_missing
if n not in reasons
}

# remove the nodes
g.remove_nodes_from(to_remove)
Expand All @@ -105,7 +121,7 @@ def complex_to_remove(x):
if remove_isolates:
isolates = list(nx.isolates(g))
g.remove_nodes_from(isolates)
reasons = {**reasons, **{n:"isolate" for n in isolates if not n in reasons}}
reasons = reasons | {n: "isolate" for n in isolates if n not in reasons}

now_size = g.number_of_nodes()
print(f"Removed {og_size - now_size} nodes from network.")
Expand Down
12 changes: 6 additions & 6 deletions skm_tools/cuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

def get_cutset(sources, targets, g):
source_sink_graph = g.copy()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function get_cutset refactored with the following changes:

  • Simplify logical expression using De Morgan identities (de-morgan)

source_sink_graph.add_node("source")
for node in sources:
if source_sink_graph.has_node(node):
Expand All @@ -15,23 +15,23 @@ def get_cutset(sources, targets, g):

source_sink_graph.add_node('sink')
for node in targets:
if source_sink_graph.has_node(node) and not (node in sources):
if source_sink_graph.has_node(node) and node not in sources:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (llm): The check 'node not in sources' is redundant because it's already implied by the surrounding 'for' loop iterating over 'targets'. This could be removed to simplify the condition.

Suggested change
if source_sink_graph.has_node(node) and node not in sources:
if source_sink_graph.has_node(node):

c = 99999
# c = 0
# for n in [x for x in source_sink_graph.predecessors(node)]:
# c += source_sink_graph.get_edge_data(n, node)['capacity']
source_sink_graph.add_edge(node, 'sink', capacity=c)

r = nx.flow.edmonds_karp(source_sink_graph, 'source', 'sink')
print(f"max_flow = {r.graph['flow_value']}")

cut_value, partition = nx.minimum_cut(source_sink_graph, 'source', 'sink', flow_func=nx.flow.edmonds_karp)
reachable, non_reachable = partition

cutset = set()
for u, nbrs in ((n, source_sink_graph[n]) for n in reachable):
cutset.update((u, v) for v in nbrs if v in non_reachable)

print(cut_value == sum(source_sink_graph.edges[u, v]["capacity"] for (u, v) in cutset) )

return sorted(cutset)
47 changes: 18 additions & 29 deletions skm_tools/cytoscape_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ def _cytoscape_safe_names(names):
def apply_builtin_style(suid, style):
style = style.lower()

if not (style in resources.BUILTIN_STYLES):
if style not in resources.BUILTIN_STYLES:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_builtin_style refactored with the following changes:

  • Simplify logical expression using De Morgan identities [×2] (de-morgan)

raise ValueError(f"apply_builtin_style expects a value in {resources.BUILTIN_STYLES}.")

style_name = {
'ckn':resources.CKN_DEFAULT_STYLE,
'pss':resources.PSS_DEFAULT_STYLE
}[style]

if not style_name in p4c.styles.get_visual_style_names():
if style_name not in p4c.styles.get_visual_style_names():
p4c.import_visual_styles(resources.get_style_xml_path())

p4c.styles.set_visual_style(style_name, network=suid)
Expand Down Expand Up @@ -90,7 +90,7 @@ def highlight_path(node_names, colour, skip_nodes=None, skip_edges=None, label_c
'''

if isinstance(skip_nodes, Sequence) and not isinstance(skip_nodes, str):
node_names = [n for n in node_names if not n in skip_nodes]
node_names = [n for n in node_names if n not in skip_nodes]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function highlight_path refactored with the following changes:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (llm): Consider using a set for 'skip_nodes' if it's expected to be large for performance benefits when checking membership.

Suggested change
node_names = [n for n in node_names if n not in skip_nodes]
skip_nodes_set = set(skip_nodes)
node_names = [n for n in node_names if n not in skip_nodes_set]


if len(node_names) == 0:
print("No more nodes to colour")
Expand All @@ -108,9 +108,7 @@ def highlight_path(node_names, colour, skip_nodes=None, skip_edges=None, label_c
network=network
)

edge_pairs = []
for s, t in zip(node_names, node_names[1:]):
edge_pairs.append((s, t))
edge_pairs = list(zip(node_names, node_names[1:]))
edges = highlight_edges(edge_pairs, colour, skip_edges=skip_edges, edge_line_width=edge_line_width, network=network)

return node_names, edges
Expand All @@ -123,7 +121,7 @@ def highlight_edges(edge_pairs, colour, skip_edges=None, edge_line_width=10, net
edges = []
for s, t in edge_pairs:
e = f"{s} (interacts with) {t}"
if not (e in skip_edges):
if e not in skip_edges:
Comment on lines -126 to +124

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function highlight_edges refactored with the following changes:

  • Simplify logical expression using De Morgan identities (de-morgan)

edges.append(e)

escaped_names = _cytoscape_safe_names(set(edges))
Expand Down Expand Up @@ -180,17 +178,15 @@ def subnetwork_edge_induced_from_paths(paths, g, parent_suid, name="subnetwork (

_, cytoscape_edges = get_path_edges(paths, g)

network_suid = p4c.networks.create_subnetwork(
return p4c.networks.create_subnetwork(

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (llm): Directly returning the result of 'create_subnetwork' is concise, but ensure that no additional processing on 'network_suid' is required before returning.

nodes=all_path_nodes,
edges=cytoscape_edges,
subnetwork_name=name,
network=parent_suid,
exclude_edges=True,
edges_by_col="shared name"
edges_by_col="shared name",
)

return network_suid
Comment on lines -183 to -192

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function subnetwork_edge_induced_from_paths refactored with the following changes:


def subnetwork_node_induced(nodes, parent_suid, name="subnetwork (node induced)"):
'''Subnetwork from existing Cystoscape network.
'''
Expand All @@ -203,14 +199,10 @@ def subnetwork_node_induced(nodes, parent_suid, name="subnetwork (node induced)"
network=parent_suid
)

network_suid = p4c.networks.create_subnetwork(
nodes=select_result['nodes'],
subnetwork_name=name,
network=parent_suid
return p4c.networks.create_subnetwork(
nodes=select_result['nodes'], subnetwork_name=name, network=parent_suid
)

return network_suid
Comment on lines -206 to -212

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function subnetwork_node_induced refactored with the following changes:


def subnetwork_neighbours(nodes, parent_suid, name="subnetwork (1st neighbours)"):
''' Node-induced neighbourhood of `nodes`.
'''
Expand All @@ -225,14 +217,10 @@ def subnetwork_neighbours(nodes, parent_suid, name="subnetwork (1st neighbours)"

neighbours = p4c.select_first_neighbors(network=parent_suid)

network_suid = p4c.networks.create_subnetwork(
nodes=neighbours['nodes'],
subnetwork_name=name,
network=parent_suid
return p4c.networks.create_subnetwork(
nodes=neighbours['nodes'], subnetwork_name=name, network=parent_suid
)

return network_suid
Comment on lines -228 to -234

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function subnetwork_neighbours refactored with the following changes:


def contrast_colour(colour):
'''To contrast label to node colours'''
rgb = int(colour.lstrip('#'), 16)
Expand Down Expand Up @@ -275,13 +263,13 @@ def apply_shortest_paths_style(sources, path_lists, target, g, edge_colors=None,
for node in nodes:
d = len(nx.shortest_path(g, source=node, target=target)) -1
path_searches_attributes[node]['distance-to-target'] = d
if not (node in skip_source):
if node not in skip_source:
path_searches_attributes[node]['node-path-source'] = source
skip_source.update([node])

_, cytoscape_edges = get_path_edges(paths, g)
for e in cytoscape_edges:
if not e in edge_priority:
if e not in edge_priority:
Comment on lines -278 to +272

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_shortest_paths_style refactored with the following changes:

edge_priority[e] = {'edge-priority': f"direct path ({source})"}

p4c.tables.load_table_data(
Expand All @@ -301,8 +289,10 @@ def apply_shortest_paths_style(sources, path_lists, target, g, edge_colors=None,
)

if node_colors:
max_len = max([path_searches_attributes[x]['distance-to-target'] \
for x in path_searches_attributes])
max_len = max(
path_searches_attributes[x]['distance-to-target']
for x in path_searches_attributes
)
node_color_mapping_range = range(0, max_len+1, int(max_len / (len(node_colors)-1)))

p4c.style_mappings.set_node_color_mapping(
Expand Down Expand Up @@ -376,8 +366,7 @@ def add_custom_png(network, create_png, style=None):

node_pngs = {}
for node in nodes:
node_png_fname = create_png(node)
if node_png_fname:
if node_png_fname := create_png(node):
Comment on lines -379 to +369

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function add_custom_png refactored with the following changes:

node_pngs[node] = {'fig_location':f"file:{str(node_png_fname.absolute())}"}

table = pd.DataFrame.from_dict(node_pngs, orient='index')
Expand Down
4 changes: 1 addition & 3 deletions skm_tools/load_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ def pss_to_networkx(edge_path=None, node_path=None):
node_df.set_index("name", inplace=True, drop=False)

def to_list(x):
if isinstance(x, str):
return x.split(',')
return None
return x.split(',') if isinstance(x, str) else None

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function pss_to_networkx refactored with the following changes:


for c in [
'ath_homologues',
Expand Down
32 changes: 23 additions & 9 deletions skm_tools/pss_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,29 @@ def filter_pss_nodes(g, node_types=None, species=None, remove_isolates=True):
# and do not have required homologues
homologue_properties = [f"{sp}_homologues" for sp in species]
no_species = [
n for n, data in g.nodes(data=True) if not (
len([h for h in homologue_properties if data[h]])>0
or
not (data['node_type'] in ['PlantCoding', 'PlantNonCoding'])
n
for n, data in g.nodes(data=True)
if not (
[h for h in homologue_properties if data[h]]
or data['node_type'] not in ['PlantCoding', 'PlantNonCoding']
)
]
to_remove.update(no_species)
reasons = {**reasons, **{n:"species missing" for n in no_species if not n in reasons}}
reasons = reasons | {
n: "species missing" for n in no_species if n not in reasons
}

if node_types:
# nodes not in keep_types
wrong_type = [n for n, data in g.nodes(data=True) if not (data['node_type'] in node_types)]
wrong_type = [
n
for n, data in g.nodes(data=True)
if data['node_type'] not in node_types
]
to_remove.update(wrong_type)
reasons = {**reasons, **{n:"wrong node type" for n in wrong_type if not n in reasons}}
reasons = reasons | {
n: "wrong node type" for n in wrong_type if n not in reasons
}
Comment on lines -19 to +41

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function filter_pss_nodes refactored with the following changes:


# now remove complexes that contain any nodes to be removed entities
as_components = []
Expand All @@ -44,9 +53,14 @@ def complex_to_remove(x):
for n in x.split("|"):
if n in as_components:
return True

complex_component_missing = [n for n in g.nodes() if complex_to_remove(n)]
to_remove.update(complex_component_missing)
reasons = {**reasons, **{n:"complex component removed" for n in complex_component_missing if not n in reasons}}
reasons = reasons | {
n: "complex component removed"
for n in complex_component_missing
if n not in reasons
}

# remove the nodes
g.remove_nodes_from(to_remove)
Expand All @@ -55,7 +69,7 @@ def complex_to_remove(x):
if remove_isolates:
isolates = list(nx.isolates(g))
g.remove_nodes_from(isolates)
reasons = {**reasons, **{n:"isolate" for n in isolates if not n in reasons}}
reasons = reasons | {n: "isolate" for n in isolates if n not in reasons}

now_size = g.number_of_nodes()
print(f"Removed {og_size - now_size} nodes from network.")
Expand Down
3 changes: 1 addition & 2 deletions skm_tools/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@
def get_style_xml_path():
'''file path on disk '''
module_path = os.path.abspath(__file__)
resource_path = os.path.join(os.path.dirname(module_path), STYLE_XML)
return resource_path
return os.path.join(os.path.dirname(module_path), STYLE_XML)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function get_style_xml_path refactored with the following changes: