Find all vertices with the same edge attribute - python

I would like to find all vertices (vertex id's) sharing the same edge attribute (so there can be tons of vertices like this) by using Igraph. This would be very convenient when I want to find all "villages" (the vertices of my graph) on a "road", let's say "Route 69" (an edge attribute).
Is there a simple way in Igraph to do this? Maybe I've overcomplicated it.
Actually what I need is the opposite of: g.es.select(_within=g.vs[2:5]) or
>>> men = g.vs.select(gender="m")
>>> women = g.vs.select(gender="f")
>>> g.es.select(_between=(men, women))
because I know the edge attribute but I don't know the vertices.
I will select the edge and hope that it will return all related vertices.
Maybe I'm only tired now, but I don't find my way around this problem. I appreciate if somebody helps me out with the right way. Or maybe there is a method I miss in tutorial and documentation. It smells like there is a very simple method to this. Thank you in advance for any advice!

First, select all the edges on Route 69:
edges = g.es.select(name="Route69")
Then iterate through the selected edges and collect the endpoints of the vertices:
vertices = set()
for edge in edges:
vertices.update(edge.tuple)
This will give you a set containing the vertex IDs of all the vertices that are incident on at least one edge with name Route69. If you need a VertexSeq, you can simply do this:
vertices = g.vs[sorted(vertices)]

You should be able to do the following:
r69edges = g.es.select(name_eq='Route69') #Select all edges where name=='Route69'
sg = r69edges.subgraph() #Create a subgraph containing only the selected edges (and attached vertices)
village_verts = sg.vs.select(name_eq='villages') #Select the vertices where name=='villages'
This assumes that 'villages' and 'Route69' are stored in an attribute called 'name' on the vertices and edges... Adjust appropriately to match your attributes.
Of course - you can squash this all into one line if you want:
village_verts = g.es.select(name_eq='Route69').subgraph().vs.select(name_eq='villages')
Not sure if this is the most efficient way (though I'm not seeing any shortcuts in the documentation), but it should get you what you're after.

Related

Networkx tools in Python

Hi i am still quite new to networkx python.
does anyone know how i can get all of the intersection?
Intersection nodes are the red circled. This is for undirected Graph, I would also very keen to know if there is also a way to get intersection for directed graph
Once i got the intersection, I also would like to get the start and the end node. the reason is I wanted to put different group to the path (from start node to end node)
Can I achieve this result too :<
If with intersections you mean nodes with more than two neighbors than you can use that exact logic like
intersections = [node for node in G.nodes() if len(list(G.neighbors(node)))>2]
H = G.copy()
H.remove_nodes_from(intersections)
components = nx.connected_components(H)
For "spotting" intersection you can issue them an attribute like this:
intersections_subgraph = nx.subgraph(G, intersetions)
nx.set_node_attributes(intersections_subgraph, True, 'intersection')
Adding intersections back into the sections should works by looping through the intersections neighbors and adding the intersection to the section the neighbors are in.
For sorting I would loop through the section to find a start point (only one edge/neighbor) and then move from node to node. Note that sets are always unordered so you will have to switch over to an ordered structure like a list.
Ill leave implementing those to you

Filtering a subgraph in graph-tool

This is a ridiculously basic question about graph-tool which should be trivial to figure out how to solve using the documentation, but I'm spinning in circles. I don't doubt that documentation comprehensive, but it certainly isn't making this easy.
GOAL: Given a graph G, extract the induced subgraph based on a list of vertices of G.
I know I should be doing this with a GraphView somehow. I get that. I also understand that I need to make a vertex PropertyMap for this. But what exactly should I be creating?
The documentation is very lacking here. For example, the page on PropertyMaps says that each PropertyMap can be of a certain type, but I haven't figured out what that means. What do the types represent? When would I want to use one type over another? Given apparently how important PropertyMaps are to the efficient usage of graph-tool, I'm a little bewildered at how unclear the docs are.
For this problem, I get the vague sense that I need to use the Boolean type, because maybe I want to set the vertices I want in the subgraph to "true" while the vertices I don't want in the subgraph to "false." But does that mean the PropertyMap I create needs to have the same length as the number of nodes in my original graph G? Or can I just provide a list of nodes and somehow let it be understood that those are the only ones to be set to True?
You are right. You have to use GraphView. In the following example a induced subgraph with vertices 0, 1, 3 are created from a complete graph with 5 vertices
from graph_tool import GraphView, generation
g = generation.complete_graph(5)
# select some vertices
vfilt = g.new_vertex_property('bool');
vfilt[0] = True
vfilt[1] = True
vfilt[3] = True
sub = GraphView(g, vfilt)
print [(g.vertex_index[e.source()], g.vertex_index[e.target()])
for e in sub.edges()]
Output
[(0, 1), (0, 3), (1, 3)]

networkx best practice getting edge attribute value while iterating over edges

Given a list of edges (or a generator). What is the most readable way to identify edges with a certain attribute value? For example all edges with an 'edge_type' of 'foo'?
Currently, my code looks like this:
for edge in nx_graph.out_edges(my_node):
edge_type = nx_graph[edge[0]][edge[1]]['edge_type']
if edge_type == 'foo':
...
Due to the many brackets this is not very easy to read...
A slightly more readable approach:
for edge in G.edges_iter(data=True):
if edge[2]['edge_type']=='foo':
...
Yet it is still not very clear (especially the [2] ). Also, I am not sure how to use it with out_edges()
Here's an option
for edge in ((u,v,data) for u,v,data in G.edges_iter(data=True) if data['edge_type']=='foo'):
...

How to get edge indices from selection?

Is there's a way to get the indices properly from a Pymel/Maya API function?
I know Pymel has a function called getEdges() however according to their docs this get's them from the selected face, however I just need them from the selected edges.
Is this possible?
While your answer will work theodox, I did find a much simpler resolution, after some serious digging!
Turns out, hiding and not very well documented, was a function ironically called indices(), I did search for this but nothing came up in the docs.
Pymel
selection[0].indices()[0]
The above will give us the integer of the selected edge. Simple and elegant!
Do you mean you just the expanded list of selected edges? That's just FilterExpand -sm 32 or cmds.filterExpand(sm=32) or pm.filterExpand(sm=32) on an edge selection. Those commands are always strings, you grab the indices out them with a regular expression:
# where objs is a list of edges, for example cmds.ls(sl=True) on an edge selection
cList = "".join(cmds.filterExpand( *objs, sm=32))
outList = set(map ( int, re.findall('\[([0-9]+)\]', cList ) ) )
which will give you a set containing the integer indices of the edges (I use sets so its easy to do things like find edges common to two groups without for loops or if tests)

Detecting border of plane in Blender Python API

I'm working on a script to generate building from plane. While having normal plane is rectangle it's quite easy - you're looking for vertices most -/+X, -/+Y, -/+Z, but what if plane is not of regular shape? Is there a nice easy solution within python api in Blender?
In fact is there any clever way to detect faces/edges/vertices on border?
Look for border edges: these will be ones that are only attached to one face. Look at the Mesh class, specifically the edges, faces and vertices attributes. Unfortunately the edges don’t contain a list of what faces they belong to, so you will have to construct such a mapping, e.g.
EdgeFaces = {} # mapping from edge to adjacent faces
for ThisFace in TheMesh.faces :
for ThisEdge in ThisFace.edge_keys :
if not ThisEdge in EdgeFaces :
EdgeFaces[ThisEdge] = []
#end if
EdgeFaces[ThisEdge].append(ThisFace.edge_keys)
#end for
#end for
Then you just look through EdgeFaces for all keys that map to single-element lists.

Categories