Source code for orbichord.graph
"""Create a graph with chords as nodes."""
from music21.chord import Chord
from music21.scale import ConcreteScale
from networkx import Graph
from orbichord.chordinate import EfficientVoiceLeading
from orbichord.generator import Generator
from typing import Callable
[docs]def createGraph(
generator: Generator,
voice_leading: EfficientVoiceLeading,
tolerance: Callable[[float], bool],
label: Callable[[Chord], str] =\
lambda chord: chord.identity
) -> Graph:
"""Create a graph as adjacency list of chords.
Parameters
----------
generator : Generator
An orbichord generator.
voice_leading : EfficientVoiceLeading
A voice leading object.
tolerance : Callable[[float], bool]
Tolerance function.
labed
Return
------
graph: Graph
Networkx Graph object.
"""
# Adjacency list
graph = Graph()
# Chord to id map
node_to_chord = {}
# Add node to the graph usign
# chord identity
for chord in generator.run():
node = label(chord)
node_to_chord[node] = chord
graph.add_node(node)
# Compute edges
vetoed_nodes = set()
# Loop over all source nodes
for source in graph.nodes:
# Vetoed source
vetoed_nodes.add(source)
# Loop over all target nodes
for target in graph.nodes:
# Check node is vetoed
if target in vetoed_nodes:
continue
# Compute distance of efficient leading voice
_, distance = voice_leading(
node_to_chord[source],
node_to_chord[target]
)
# If within tolerance add edge
if tolerance(distance):
graph.add_edge(
source,
target,
distance = distance
)
return graph, node_to_chord
[docs]def convertGraphToData(
graph: Graph
):
"""Convert a chord graph to columnal dataset.
Parameters
----------
graph : Graph
A graph of chords.
Return
------
edges : list
List of graph edges.
vertices : list
List of vertices
"""
vertices= []
edges = []
index = 0
node_to_index = {}
for node, neighbors in graph.adjacency():
vertices.append({
'name': node,
'group': 1
})
node_to_index[node] = index
index += 1
for node, neighbors in graph.adjacency():
for neighbor, edge in neighbors.items():
edges.append({
'source': node_to_index[node],
'target': node_to_index[neighbor],
'value': edge['distance']
})
return edges, vertices