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₃]⁽³²⁾'