How can I correctly index elements in Python? - python

I am trying to implement the following function to train a neural network as below:
# Here I am trying to convert train edges to nx.graph
data.edge_index = torch.from_numpy(edges(data._train)).long()
G = nx.Graph()
edge_numpy = data.edge_index.numpy()
edge_list = []
for i in range(data.num_edges):
edge_list.append(tuple(edge_numpy[:, i]))
G.add_edges_from(edge_list)
data.G = G
# These are nodes from training graph
nodes = list(G.nodes())
new = []
# These are features for the whole graph
feature = data.x.detach().cpu().numpy()
# Here the all set is calculated from all nodes in whole graph
all = get_seedsets(data.num_nodes, c=0.5)
print(all)..... [array([5, 1, 2]), array([1])]
for i in range(len(all)):
temp_id = all[i]
specific_features=np.zeros((feature.shape[0], feature.shape[1])
# Here I am trying to copy features of each node in the all to specific_features
for v in range(len(nodes)):
y = nodes.index(v).........*ValueError: 180 is not in list*
if y in temp_id:
specific_features[nodes[v]] = feature[y]
However, I am getting this error:
V`alueError: 180 is not in list*
What can I do?

Related

pyviz to visualize multiple separate graphs into one and filter by graph

I am generating a graph to visualize the association's rules and using pyviz to get an interactive visualization. Currently, I saved data in one graph but I would like to save different data into separate graphs and represent it all in one network graph, then set a drop-down menu to filter the graph and only show that part of the whole network graph.
I would like to have, graph_1,graph_2, and graph_3 saved in one general graph and do post filtering where I can choose which to focus.
I am using the below code to generate and visualize one graph:
import networkx as nx
from pyvis.network import Network
def draw_graph(rules, saveName):
rules_to_show = len(rules)
G1 = nx.DiGraph()
color_map=[]
N = 50
colors = np.random.rand(N)
strs=[]
mydic={}
median = rules['confidence'].median()
for i in range (rules_to_show):
conf = rules.iloc[i]['confidence']
strs.append(str('R')+str(i))
G1.add_nodes_from(["R"+str(i)])
for a in rules.iloc[i]['antecedents']:
G1.add_nodes_from([a])
if conf > median:
G1.add_edge(a, "R"+str(i), color='lightgrey' , value = conf*0.01)
else:
G1.add_edge(a, "R"+str(i), color='orange' , value = conf*0.01)
for c in rules.iloc[i]['consequents']:
G1.add_nodes_from([a])
if conf > median:
G1.add_edge("R"+str(i), c, color='lightgrey', value = conf*0.01)
else:
G1.add_edge("R"+str(i), c, color='orange', value = conf*0.01)
for node in G1:
# print(node)
found_a_string = False
for item in strs:
# print(item)
if node==item:
found_a_string = True
if found_a_string:
color_map.append("lightblue")
else:
color_map.append("lightgreen")
for index,row in dataset.iterrows():
mydic.update({row["items"]:(row['support'])})
x={}
for node in G1:
if node in mydic:
x.update({node:mydic.get(node)})
else:
x.setdefault(node, 0.0001)
nodes, values = zip(*x.items())
nt= Network(notebook=True,
cdn_resources="remote",
bgcolor="#222222",
font_color="white",
height="750px",
width="100%",
select_menu=True,
filter_menu=True)
nt.add_nodes(list(nodes), value=[int(v*10000) for v in values], color=color_map)
nt.from_nx(G1)
nt.repulsion(node_distance=100, spring_length=500)
nt.show_buttons(filter_=['physics'])
nt.show(str(saveName)+'.html')
draw_graph (update_df, 'test')

Extract strain at nodes specified in node set [Abaqus python odb access]

Given an Abaqus odb-file including a node set (e.g. 'ALL_SECS').
NODAL-quantities like coordinates ('COORD') or displacement ('U') can be extracted at the nodes of the node set by the following pattern:
select step, frame and fieldoutput (e.g. 'COORD', 'U')
getSubset(region=) of the fieldoutput
get attributes of the resulting values
How can INTEGRATION_POINT-quantities be extracted / interpolated at nodes of the node set?
How can fieldoutput at NODAL-position be requested using abaqus-python?
from odbAccess import *
import numpy as np
# Helper function
def values_to_array(values, dim=2, item='data'):
length = len(values)
array = np.zeros((length, dim), dtype='float64')
for index in range(length):
array[index, :] = getattr(values[index], item)
return array
# Prepare and open
odb = openOdb(path='job.odb') # Solution of 2D-plane-stress model
instances = odb.rootAssembly.instances
instance = instances['PART']
sett = instance.nodeSets['ALL_SECS']
step = odb.steps.keys()[-1]
# Get coordinates and number of nodes in node set
frame = odb.steps[step].frames[-1]
values_xy = frame.fieldOutputs['COORD'].getSubset(region=sett).values
xy = values_to_array(values=values_xy, dim=2, item='dataDouble')
nbr_xy = len(values_xy)
print('len(values_xy)')
print(len(values_xy))
# Get nodal-quantity and number of nodes in node set
uvw = np.zeros((nbr_xy, 2), dtype=float)
outp = odb.steps[step].frames[-1].fieldOutputs['U']
values_u = outp.getSubset(region=sett).values
uvw = values_to_array(values=values_u, dim=2, item='dataDouble')
print('len(values_u)')
print(len(values_u))
eps = np.zeros((nbr_xy, 4), dtype=float)
outp = odb.steps[step].frames[-1].fieldOutputs['E']
values_eps = outp.getSubset(position=ELEMENT_NODAL, region=sett).values
# values_eps = outp.getSubset(position=ELEMENT_NODAL).getSubset(region=sett).values
print('len(values_eps)')
print(len(values_eps))
values_eps_nodal = outp.getSubset(position=NODAL, region=sett).values
print('len(values_eps_nodal)')
print(len(values_eps_nodal))
Output:
len(values_xy)
147
len(values_u)
147
len(values_eps)
408
len(values_eps_nodal)
0
The following solution is a workaround to get total strain (Fieldoutput 'E') at nodes, specified in the node set 'ALL_SECS'. As the order of the extracted nodes is not known, location information, i.e. coordinates of the nodes, is extracted as well.
The i-th strain in eps is the strain at the i-th coordinate in xy.
This feature seems not to exist in the Abaqus API.
Node-specific data, like displacements, can easily be extracted, see uv.
Key steps to extract strain data at element nodes and location:
Identify coordinates
Identify mapping nodeLabel -> index
Combine values at nodes, extrapolated from different elements using moving average. (See link for explanations)
Note: 2D model odb
from odbAccess import *
import numpy as np
import pickle
from operator import attrgetter
def values_to_array(values, dim=2, item='data', dtype=np.float64):
'''Thanks to https://stackoverflow.com/a/46925902/8935243'''
array = np.array(
map(attrgetter(item), values),
dtype=dtype,
)
return array
def values_to_index_mapping(values, item='nodeLabel', check=True):
node_labels = values_to_array(values, dim=1, item=item, dtype=np.int64)
if check:
assert len(set(node_labels)) == len(node_labels)
mapping = {}
for index, label in enumerate(node_labels):
mapping[label] = index
return mapping
odb = openOdb(path='job.odb')
instances = odb.rootAssembly.instances
instance = instances['PART']
sett = instance.nodeSets['ALL_SECS']
step = odb.steps.keys()[-1]
# Coordinates
frame = odb.steps[step].frames[-1]
values = frame.fieldOutputs['COORD'].getSubset(region=sett).values
xy = values_to_array(values=values, dim=2, item='data')
# Dimensions
nbr_xy = len(values)
# Mapping: nodeLabel -> index
index_map = values_to_index_mapping(values=values, check=True)
# Displacements
uv = np.zeros((nbr_xy, 2), dtype=float)
outp = odb.steps[step].frames[-1].fieldOutputs['U']
values = outp.getSubset(region=sett).values
uv[:, :] = values_to_array(values=values, dim=2, item='data')
# Strains
eps = np.zeros((nbr_xy, 4), dtype=float)
tmp = np.zeros((nbr_xy, 1), dtype=float)
values_eps = odb.steps[step].frames[-1].fieldOutputs['E'].getSubset(
position=ELEMENT_NODAL,
region=sett,
).values
# Moving average, as ELEMENT_NODAL does no averaging
# and returns multiple values for nodes in sett
for ee in values_eps:
index = index_map[ee.nodeLabel]
tmp[index] += 1
eps[index] = (eps[index] * (tmp[index] - 1) + ee.data) / tmp[index]
odb.close()

How can I create a non-bipartite graph in a bi-partite layout

I have a graph with lots of nodes. I am going to segregate them based on their timesteps. Let's say I have 3 timesteps and I have 5 nodes for each time step. So I want to create a 3-columned graph where each column has 5 nodes. So if we imagine, it needs to like a bipartite layout.
But this is not a bipartite graph and hence I am not sure how to proceed
# Greate your Bipartite graph object
G = nx.Graph()
y_out = [6, 6, 12 ,8, 23, 23]
# Add nodes to set 0 and 1
G.add_nodes_from(y_out, bipartite=0)
G.add_nodes_from(['a6', 'b6', 'c12', 'd8', 'd23', 'e23'], bipartite=1)
# # Add edges between exclusive sets
# G.add_edges_from([dets_tuple])
top_nodes = {n for n, d in G.nodes(data=True) if d['bipartite'] == 0}
bottom_nodes = set(G) - top_nodes
print("top:", top_nodes)
print("bottom: " ,bottom_nodes)
# Visualize the graph
plt.subplot(121)
nx.draw_networkx(
G, pos=nx.drawing.layout.bipartite_layout(G, top_nodes))
plt.show()
UPDATED CODE:
unique_frames = set(y_out[:, 0])
print("Generate dynamic graph")
# Visualize the graph
plt.subplot(121)
for i in unique_frames:
# find indices that belong to the same frame
idx = np.where(y_out[:, 0] == i)
print("Comparing frame no: ", i)
print("Idx : ", idx)
# embed()
curr_nodes = np.asarray(idx)[0]
# Add nodes to set 0 and 1
G.add_nodes_from(curr_nodes, bipartite=i)
# compute partition nodes
top_nodes = {n for n, d in G.nodes(data=True) if d['bipartite'] == i}
# Draw Graph
nx.draw_networkx(G, pos=nx.drawing.layout.bipartite_layout(G, top_nodes))
plt.show(block=False)
plt.pause(0.5)
This literally shows me a bipartite graph. I have plugged in the nodes temporarily so that it respects the bipartite rule. But ideally I can not have one. How can I construct a normal multiple connected graph with a bipartite layout
Update: The new updated code is creating graphs, but on the same column. I not sure how to space them horizontally

Python Connected Components edges list

I use these algorithms in python for finding connected components from edges.
components = []
def connected_components(pairs):
for a, b in pairs:
for component in components:
if a in component:
for i, other_component in enumerate(components):
if b in other_component and other_component != component: # a, and b are already in different components: merge
component.extend(other_component)
components[i:i+1] = []
break # we don't have to look for other components for b
else: # b wasn't found in any other component
if b not in component:
component.append(b)
break # we don't have to look for other components for a
if b in component: # a wasn't in in the component
component.append(a)
break # we don't have to look further
else: # neither a nor b were found
components.append([a, b])
return components
This algorithms return components like this :
[ [n1,n2,n4],[n3,n5] ]
I would like to have the list of all edges in connected components like this :
[ [(n1,n2),(n2,n4),(n4,n1)],[(n3,n5)] ]
in the same order of the previous list but i don't know how creates this list
Thank you for your help.
Note: This doesn't require any python dependency.
I will share my approach, with recursive depth-first search. I am assuming graph is bi-directional and the following code can be easily manipulated for directed graph.
pairs = [] // edge list
adj_list = {} // adjacency list
vis = [] // visited_list
connected_components = [] // contains all the connected components
temp_component = []
// basic depth first search
def dfs( node ):
vis[node] = "true"
temp_component.append(node)
for neighbour in adj_list[node]:
if vis[neighbour] == "false":
dfs(neigbour)
//main
for a,b in pairs:
if a not in adj_list:
adj_list[a] = []
if b not in adj_list:
adj_list[b] = []
adj_list[a].append(b)
adj_list[b].append(a)
vis["a"] = "false"
vis["b"] = "false"
for a,b in pairs:
temp_component = []
if vis[a] == "false":
dfs(a)
if len(temp_component) > 0:
connected_components.append(temp_component)
// once you have connected components you can get the edge lists in connected component as well
answer = []
for component in connected_components:
temp_pairs = [] // contains the pair of edges for the current connected component
for node in component:
for i,j in pairs:
if (node == i or node == j) and (i,j) not in temp_node:
temp_node.append(i,j)
answer.append(temp_pairs)
Create a mini graph in python using apgl library.
You can use SparseGraph module from apgl. from apgl.graph import SparseGraph
Initiate a sparsegraph with number of nodes required.
graph = SparseGraph(num_vertices)
Then you can create a mini graph by adding edges between nodes of graph.
graph.addEdge(component1, component2)
Then just use findConnectedComponents function to find connected components.
graph.findConnectedComponents()
I know this is an old question, but I came across the same problem and was not glad with the performance of the given answers. So I wanted to share my own solution using scipy's connected_components and shortest_path functions to handle arbitrary edge-soups.
from scipy.sparse import csr_matrix, csgraph
import numpy as np
def coords_to_indices(coords):
"""
Decompose a set of primitives defined by vertex-coordinates to their shared vertices and primitive indices
Parameters
----------
coords : array like
A NxMxD array, where N is the number of primitives, M the number of vertices per primitive and D the number of dimensions of each vertex
Returns
-------
vertices : NDArray
UxD array containing the unique vertices
primitives : NDArray
NxM array containing the indices of vertices building the primitives
"""
coords = np.asarray(coords)
vert_dim = coords.shape[-1]
prim_dim = coords.shape[1]
vertices, rev_indx = np.unique(coords.reshape((-1, vert_dim)), axis=0, return_inverse=True)
primitives = rev_indx.reshape((coords.shape[0], prim_dim))
return vertices, primitives
def is_ordered(edge_indices) -> bool:
"""
Check if the edges are ordered or not
Parameters
----------
edge_indices : Nx2 array of indices
Indices of the edge vertices
Returns
-------
bool
True, if all edges are in order. That means, every edge is connected with the following one by its second vertex.
"""
edge_indices = np.asarray(edge_indices)
e_flat = edge_indices.flatten()[1:-1]
return all(e_flat[1::2] - e_flat[::2] == 0)
def reorder_edges(connected_edges):
"""
Reorder an unsorted list of edges (indices Nx2) or coordinates (Nx2xM) so that:
- Each edge is connected to the next edge
- The connection is made from the second vertex to the first vertex of the following edge
Parameters
----------
connected_edges : array-like, Nx2 indices or Nx2xM coordinates
edges that build the segment. all edges have to be connected, but every vertex has to be shared by exactly 2 edges.
If the segment is not closed, two vertices are allowed to rise up in only one edge (the ends).
Returns
-------
NDArray - like the input
The edges, reordered
"""
connected_edges = np.asarray(connected_edges)
if is_ordered(connected_edges):
return connected_edges
if connected_edges.ndim == 3 and connected_edges.shape[1] == 2 and np.issubdtype(connected_edges.dtype, np.floating):
# vertex coordinates given, transform to edge indices and back
verts, edges = coords_to_indices(connected_edges)
e_ordered = reorder_edges(edges)
return verts[e_ordered]
assert np.issubdtype(connected_edges.dtype, np.integer) and connected_edges.ndim == 2 and connected_edges.shape[1] == 2, "Wrong shape"
edges = connected_edges
n_edges = edges.shape[0]
n_verts = edges.max() + 1
# find the unique indices and counts of the vertices
idxs, counts = np.unique(connected_edges.flat, return_counts=True)
# translate edges to monotone space
if np.all(counts == 2):
# cyclic contour (all vertices are counted twice)
# wo have to cut the cycle and restore it afterwards. Otherwise, its hard to follow the two valid paths
edges = edges[1:]
n_edges -= 1
new_edges = reorder_edges(edges)
# add the missing piece. Due to the strict order of the indices, this should always be between the very first and very last index
new_edges = np.row_stack((new_edges, (new_edges[-1, -1], new_edges[0, 0])))
return new_edges
# open contour
# find the open ends in the chain of segments
ends = idxs[counts == 1]
assert len(ends) == 2, "More than 2 unconnected segments found. not a contiguous contour"
# lets begin the connection walk on one of the end-segments. I choose the minimum, so maybe the indices are rising again
start_index, end_index = np.sort(ends)
# build sparse matrix of edge relations
csm = csr_matrix((np.full(n_edges, 1, dtype=np.bool_), (edges[:, 0], edges[:, 1])), (n_verts, n_verts))
# get shortest path and number of hops
n_hops, prev_idx = csgraph.shortest_path(csm, directed=False, indices=start_index, return_predecessors=True, unweighted=True)
# limit to the existing vertices
n_hops = n_hops[idxs]
prev_idx = prev_idx[idxs]
vert_order = np.argsort(n_hops)
assert np.all(np.isfinite(n_hops)), "Unreachable parts detected"
# check that the hops are increasing monotonously, otherwise something went wrong
dst = n_hops[vert_order]
assert np.all(dst[1:] - dst[:-1] == 1), "path not contiguous... something went wrong"
# get indices of neighbors
ordered_idxs = prev_idx[vert_order][1:]
# add the farthest node
ordered_idxs = np.append(ordered_idxs, end_index)
new_edges = np.column_stack((ordered_idxs[:-1], ordered_idxs[1:]))
return new_edges
def find_connected(edges):
"""
Find and return connected components in a soup of edges. Each component will be returned as an ordered list of edges
Parameters
----------
edges : array_Like
A list of edges. Either as a Nx2 list of indices or as a Nx2xD list of vertex coordinates per edge
Returns
-------
List[NDArray]
A list of Mx2 or Mx2xD arrays (depending on the input type), each containing an ordered list of connected (and maybe cyclic) edges
"""
if edges.ndim == 3 and edges.shape[1] == 2 and np.issubdtype(edges.dtype, np.floating):
# vertex coordinates given, transform to edge indices and back
verts, edges = coords_to_indices(edges)
connected_edges = find_connected(edges)
# return the result as coordinate array
return [verts[e] for e in connected_edges]
# get number of edges and maximum number of vertices
n_edges = edges.shape[0]
n_verts = edges.max() + 1
# create a sparse matrix of the relations
csm = csr_matrix((np.full(n_edges, 1, dtype=np.bool_), (edges[:, 0], edges[:, 1])), (n_verts, n_verts))
# get number and labels of the connected components. labels refer to the vertices
n_c, labels = csgraph.connected_components(csm, directed=False, return_labels=True)
# get the association to the edges. should not matter which column
edge_labels = labels[edges]
assert np.all(edge_labels[:, 0] == edge_labels[:, 1])
connected_edges = []
for label in range(n_c):
# get mask for current label:
edge_mask = edge_labels[:, 0] == label
if not np.any(edge_mask):
#this vertex was no member of any edge
continue
# iterate labels and gather all edges of that label
edges_l = edges[edge_mask, :]
# reorder if necessary
if not is_ordered(edges_l):
edges_l = reorder_edges(edges_l)
connected_edges.append(edges_l)
return connected_edges
Short Example:
def makePoly(npts=360, r=10):
angles = np.linspace(0, 2*np.pi, npts)
x = np.sin(angles) * r
y = np.cos(angles) * r
return x, y
# create a polygon
verts = np.array(makePoly(16)).T
# create the edges
edges = np.column_stack((np.arange(verts.shape[0]), np.arange(verts.shape[0])+1))
# close the loop
edges[-1, -1] = 0
# shuffe all edges
np.random.seed(123)
np.random.shuffle(edges)
# remove some edges, so we get multiple chains
edges = np.delete(edges, [1, 2, 3], axis=0)
# swap some vertex orders
swap = [4, 5, 6, 7, 8, 9]
edges[swap, :] = edges[swap, :][:, [1, 0]]
# now reorder everything
edges_ordered = find_connected(edges)
print(edges_ordered)
Result is
[
array([[ 0, 15],
[15, 14],
[14, 13],
[13, 12],
[12, 11]]),
array([[1, 2],
[2, 3],
[3, 4]]),
array([[ 5, 6],
[ 6, 7],
[ 7, 8],
[ 8, 9],
[ 9, 10]])
]

Not able to set threshold in facerec framework ( face recognition)

I am new to face recognition. I am trying to do face recognition with the help of bytefish facerec framework. It works fine but results are not very accurate. Therefore, I want to put threshold. As per suggested on his page (https://github.com/bytefish/facerec), I should be able to do it. However, explanation on page isnt very clear. So heres what I am doing.
My classifier
def predict(self, q):
distances = []
for xi in self.X:
xi = xi.reshape(-1,1)
d = self.dist_metric(xi, q)
distances.append(d)
if len(distances) > len(self.y):
raise Exception("More distances than classes. Is your distance metric correct?")
distances = np.asarray(distances)
# Get the indices in an ascending sort order:
idx = np.argsort(distances)
# Sort the labels and distances accordingly:
sorted_y = self.y[idx]
sorted_distances = distances[idx]
# Take only the k first items:
sorted_y = sorted_y[0:self.k]
sorted_distances = sorted_distances[0:self.k]
# Make a histogram of them:
hist = dict((key,val) for key, val in enumerate(np.bincount(sorted_y)) if val)
# And get the bin with the maximum frequency:
predicted_label = max(hist.iteritems(), key=op.itemgetter(1))[0]
# A classifier should output a list with the label as first item and
# generic data behind. The k-nearest neighbor classifier outputs the
# distance of the k first items. So imagine you have a 1-NN and you
# want to perform a threshold against it, you should take the first
# item
return [predicted_label, { 'labels' : sorted_y, 'distances' : sorted_distances }]
My model
def predict(self, X):
q = self.feature.extract(X)
return self.classifier.predict(q)
My server.py which generates the output
def get_prediction(image_data):
image = preprocess_image(image_data)
prediction = model.predict(image)
predicted_label = prediction[0]
classifier_output = prediction[1]
distance = classifier_output['distances'][0]
#distance = classifier.predict(self, q)
#distance = 11
if distance > 10.0:
return "nonsense"
else:
print prediction
So the problem is I am not able to get the distance here. Please help
after a while I was able to solve the problem. Threshold should be done in classifier file not in server.py.
Solution
distances = []
for xi in self.X:
xi = xi.reshape(-1,1)
d = self.dist_metric(xi, q)
distances.append(d)
if len(distances) > len(self.y):
raise Exception("More distances than classes. Is your distance metric correct?")
distances = np.asarray(distances)
# Get the indices in an ascending sort order:
idx = np.argsort(distances)
# Sort the labels and distances accordingly:
sorted_y = self.y[idx]
sorted_distances = distances[idx]
# Take only the k first items:
sorted_y = sorted_y[0:self.k]
sorted_distances = sorted_distances[0:self.k]
#sorted_distances = 1134.04873217
# Make a histogram of them:
hist = dict((key,val) for key, val in enumerate(np.bincount(sorted_y)) if val)
# And get the bin with the maximum frequency:
predicted_label = max(hist.iteritems(), key=op.itemgetter(1))[0]
# A classifier should output a list with the label as first item and
# generic data behind. The k-nearest neighbor classifier outputs the
#global unknown
if sorted_distances > 1800 :
return [predicted_label]
else:
return [predicted_label]

Categories

Resources