importnetworkxasnxfromcollectionsimportCounterdiagrams=defaultdict(list)particle_counts=defaultdict(Counter)for(a,b),neighborsincommon_neighbors.items():# Build up the graph of connections between the
# common neighbors of a and b.
g=nx.Graph()foriinneighbors:forjinset(nl.point_indices[nl.query_point_indices==i]).intersection(neighbors):g.add_edge(i,j)# Define the identifiers for a CNA diagram:
# The first integer is 1 if the particles are bonded, otherwise 2
# The second integer is the number of shared neighbors
# The third integer is the number of bonds among shared neighbors
# The fourth integer is an index, just to ensure uniqueness of diagrams
diagram_type=2-int(binnl.point_indices[nl.query_point_indices==a])key=(diagram_type,len(neighbors),g.number_of_edges())# If we've seen any neighborhood graphs with this signature,
# we explicitly check if the two graphs are identical to
# determine whether to save this one. Otherwise, we add
# the new graph immediately.
ifkeyindiagrams:isomorphs=[nx.is_isomorphic(g,h)forhindiagrams[key]]ifany(isomorphs):idx=isomorphs.index(True)else:diagrams[key].append(g)idx=diagrams[key].index(g)else:diagrams[key].append(g)idx=diagrams[key].index(g)cna_signature=key+(idx,)particle_counts[a].update([cna_signature])