198 lines
5.4 KiB
Python
198 lines
5.4 KiB
Python
from setclass.setclass import SetClass
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Functional tests
|
|
|
|
|
|
def test_zero_normalised_pc():
|
|
"Pitch classes are normalised to start at zero"
|
|
a = SetClass(0, 1, 3)
|
|
assert a == SetClass(1, 2, 4)
|
|
assert a == SetClass(4, 5, 7)
|
|
|
|
|
|
def test_modulo_pc():
|
|
"Pitch classes are normalised to modulo tonality (12)"
|
|
a = SetClass(0, 1, 3)
|
|
assert a == SetClass(12, 13, 15) # modulo down
|
|
assert a == SetClass(-11, -9, -12) # modulo up
|
|
|
|
|
|
def test_negative_pc():
|
|
"Negative pitch classes are modulo tonality (12)"
|
|
a = SetClass(0, 9, 10)
|
|
assert a == SetClass(-3, -2, 0)
|
|
|
|
|
|
def test_unordered_pc():
|
|
"Set classes are unordered; normalised to incremental sort"
|
|
a = SetClass(0, 1, 3)
|
|
assert a == SetClass(0, 3, 1)
|
|
assert a == SetClass(3, 0, 1)
|
|
assert a == SetClass(1, 3, 0)
|
|
assert a == SetClass(1, 0, 3)
|
|
assert a == SetClass(3, 1, 0)
|
|
|
|
|
|
def test_resolve_duplicate_pc():
|
|
"Set classes are sets, so duplicates (including after modulo) are eliminated"
|
|
a = SetClass(0, 1, 3)
|
|
assert a == SetClass(0, 1, 3, 3, 1)
|
|
assert a == SetClass(0, 12, 1, -11, 15)
|
|
assert a == SetClass(12, 1, -11, 15, -9)
|
|
|
|
|
|
def test_interval_vector():
|
|
"Set classes have an interval vector"
|
|
test = [
|
|
# 2-tuple of set class, expected interval vector
|
|
(SetClass(0, 3, 4, 7, 8, 11), [3, 0, 3, 6, 3, 0]),
|
|
(SetClass(0, 1, 3, 5, 6, 8, 10), [2, 5, 4, 3, 6, 1]),
|
|
]
|
|
for (sc, iv) in test:
|
|
assert sc.interval_vector == iv
|
|
|
|
|
|
def test_interval_vector_invarant():
|
|
"The interval vector is invariant under inversion and transposition (rotation)"
|
|
test = [
|
|
# 2-tuple of set class, expected interval vector
|
|
(SetClass(0, 3, 4, 7, 8, 11), [3, 0, 3, 6, 3, 0]),
|
|
(SetClass(0, 1, 3, 5, 6, 8, 10), [2, 5, 4, 3, 6, 1]),
|
|
]
|
|
for (sc, iv) in test:
|
|
for version in (sc.versions + sc.inversion.versions):
|
|
assert version.interval_vector == iv
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Example Forte 5-20 set class
|
|
f520 = SetClass(0, 1, 5, 6, 8)
|
|
|
|
|
|
def test_tonality():
|
|
"Set classes has a default tonality of 12"
|
|
assert f520.tonality == 12
|
|
|
|
|
|
def test_cardinality():
|
|
"Set classes has a set cardinality"
|
|
assert f520.cardinality == 5
|
|
|
|
|
|
def test_brightness():
|
|
"Set classes have a brightness (sum of normalised pitch class values)"
|
|
assert f520.brightness == 20
|
|
|
|
|
|
def test_pitch_classes():
|
|
"Set classes have pitch classes"
|
|
assert len(f520) == 5
|
|
assert len(f520.pitch_classes) == 5
|
|
|
|
|
|
def test_adjacency_intervals():
|
|
"Set classes have a set of adjacency intervals"
|
|
assert len(f520.adjacency_intervals) == 5
|
|
|
|
|
|
def test_versions():
|
|
"Set classes have a set of transpositions (rotations)"
|
|
assert len(f520.versions) == 5
|
|
|
|
|
|
def test_brightest_form():
|
|
b = f520.brightest_form
|
|
assert b in f520.versions
|
|
assert b == SetClass(0, 4, 5, 9, 10)
|
|
assert b.leonard_notation == '[0₄4₁5₄9₁T₂]⁽²⁸⁾'
|
|
|
|
|
|
def test_darkest_form():
|
|
d = f520.darkest_form
|
|
assert d in f520.versions
|
|
assert d == SetClass(0, 1, 3, 7, 8)
|
|
assert d.leonard_notation == '[0₁1₂3₄7₁8₄]⁽¹⁹⁾'
|
|
|
|
|
|
def test_rahn_normal_form():
|
|
r = f520.rahn_normal_form
|
|
assert r in f520.versions
|
|
assert r == SetClass(0, 1, 5, 6, 8)
|
|
|
|
|
|
def test_inversion():
|
|
i = f520.inversion
|
|
assert i not in f520.versions
|
|
assert i not in f520.complement.versions
|
|
assert i not in f520.complement.inversion.versions
|
|
assert i == SetClass(0, 4, 6, 7, 11)
|
|
|
|
|
|
def test_leonard_notation():
|
|
assert f520.leonard_notation == '[0₁1₄5₁6₂8₄]⁽²⁰⁾'
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Complement of Forte 5-20 set class: Forte 7-20
|
|
|
|
def test_complement():
|
|
assert f520.complement == SetClass(0, 1, 2, 5, 7, 8, 9)
|
|
|
|
|
|
def test_complement_tonality():
|
|
assert f520.complement.tonality == 12
|
|
|
|
|
|
def test_complement_cardinality():
|
|
assert f520.complement.cardinality == 7
|
|
|
|
|
|
def test_complement_brightness():
|
|
assert f520.complement.brightness == 32
|
|
|
|
|
|
def test_complement_pitch_classes():
|
|
assert len(f520.complement) == 7
|
|
assert len(f520.complement.pitch_classes) == 7
|
|
|
|
|
|
def test_complement_adjacency_intervals():
|
|
assert len(f520.complement.adjacency_intervals) == 7
|
|
|
|
|
|
def test_complement_versions():
|
|
assert len(f520.complement.versions) == 7
|
|
|
|
|
|
def test_complement_rahn_normal_form():
|
|
r = f520.complement.rahn_normal_form
|
|
assert r in f520.complement.versions
|
|
assert r == SetClass(0, 2, 3, 4, 7, 8, 9)
|
|
|
|
|
|
def test_complement_inversion():
|
|
i = f520.complement.inversion
|
|
assert i not in f520.versions
|
|
assert i not in f520.inversion.versions
|
|
assert i not in f520.complement.versions
|
|
assert i == SetClass(0, 3, 4, 5, 7, 10, 11)
|
|
|
|
|
|
def test_complement_brightest_form():
|
|
b = f520.complement.brightest_form
|
|
assert b in f520.complement.versions
|
|
assert b == SetClass(0, 3, 5, 6, 7, 10, 11)
|
|
assert b.leonard_notation == '[0₃3₂5₁6₁7₃T₁E₁]⁽⁴²⁾'
|
|
|
|
|
|
def test_complement_darkest_form():
|
|
d = f520.complement.darkest_form
|
|
assert d in f520.complement.versions
|
|
assert d == SetClass(0, 1, 2, 5, 6, 7, 10)
|
|
assert d.leonard_notation == '[0₁1₁2₃5₁6₁7₃T₂]⁽³¹⁾'
|
|
|
|
|
|
def test_complement_leonard_notation():
|
|
assert f520.complement.leonard_notation == '[0₁1₁2₃5₂7₁8₁9₃]⁽³²⁾'
|