class SetAnalysis(unittest.TestCase): def setUp(self): self.amaj = PcSet('9B12468') self.empty = PcSet([]) # ivec def test_ivec_ait1(self): ait1 = PcSet('0146') self.assertEqual(ait1.ivec(), [1] * 6) def test_ivec_ait2(self): ait2 = PcSet('0137') self.assertEqual(ait2.ivec(), [1] * 6) def test_ivec_empty(self): self.assertEqual(self.empty.ivec(), [0] * 6) # cvec def test_cvec(self): """ Tests the fundamental definition of cvec: that a given value at index n will be the number of common tones for the operation TnI. """ cvec = self.amaj.cvec() for n in range(12): original = set(self.amaj) transformed = set(self.amaj.invert().transpose(n)) common_tones = len(original & transformed) self.assertEqual(common_tones, cvec[n]) def test_cvec_empty(self): self.assertEqual(self.empty.cvec(), [0] * 12)
def test_union(self): """ Tests union by constructing the chromatic scale from 8 transposed major chords. (Cmaj -> Fmaj -> ... -> Bmaj) """ maj = PcSet('047') circle = [maj.T(n * 5) for n in range(8)] chromo = reduce(union, circle) self.assertEqual(set(chromo), set(range(12)))
def test_common(self): """ Very similar to the test applied to cvec in test_pcset.py: finds the common tone vector, then makes sure the common tones are actually there for each value of TnI. """ c = PcSet('024579B') cvec = c.cvec() for n in range(12): self.assertEqual(len(common(c, c.TnI(n))), cvec[n])
def setUp(self): self.a = PcSet('9047B2') self.b = PcSet('047B25') self.c = self.b.TnI(9) self.d = PcSet('9048AB') self.forte42 = PcSet([0, 1, 2, 4]) self.forte413 = PcSet([0, 1, 3, 6]) self.forte43 = PcSet([0, 1, 3, 4]) self.forte510 = PcSet([0, 1, 3, 4, 6]) self.forte5Z12 = PcSet([0, 1, 3, 5, 6]) self.forte5Z36 = PcSet([0, 1, 2, 4, 7])
def setUp(self): # Obvious: # The linear ascending chromatic scale. self.obvious = ToneRow(range(12)) # Obscure: # An example of using a simple pcset as a generator # for a tonerow . . . one day there will be a function # like this, but for now, we hack . . . . a = PcSet('015') self.obscure = ToneRow( str(a) + str(a.TnI(7)) + str(a.T(10)) + str(a.TnI(9)))
class ShorthandMethods(unittest.TestCase): def setUp(self): self.pcs = PcSet('0146') def test_T(self): a = self.pcs.T(3) b = self.pcs.transpose(3) self.assertEqual(list(a), list(b)) def test_I(self): a = self.pcs.I() b = self.pcs.invert() self.assertEqual(list(a), list(b)) def test_TnI(self): a = self.pcs.TnI(3) b = self.pcs.invert().transpose(3) self.assertEqual(list(a), list(b)) def test_Ixy(self): """ Tests the principle that the two specified pitches should transform into each other. """ n = list(self.pcs) a = list(self.pcs.Ixy(1, 4)) b = list(self.pcs.invert().transpose(5)) self.assertEqual(a, b) self.assertEqual(a[1], n[2]) self.assertEqual(a[2], n[1])
class TransformationRelationships(unittest.TestCase): def setUp(self): self.cmaj = PcSet('047') self.amaj = PcSet('914') self.cmin = PcSet('037') self.caug = PcSet('048') # symmetry 3 self.cscale = PcSet('024579B') # symmetry 1 self.c7b5 = PcSet('046A') # symmetry 2 self.dim = PcSet('0369') # symmetry 4 def fulltest(self, a, b, expected_Tn, expected_TnI): result = op_path(a, b) self.assertEqual(result.Tn, expected_Tn) self.assertEqual(result.TnI, expected_TnI) def test_op_path_none(self): self.fulltest(self.cmaj, self.caug, [], []) def test_op_path_Tn(self): self.fulltest(self.cmaj, self.amaj, [9], []) def test_op_path_TnI(self): self.fulltest(self.cmaj, self.cmin, [], [7]) def test_symmetry(self): trials = [self.cmaj, self.cscale, self.c7b5, self.caug, self.dim] for x in range(5): self.assertEqual(symmetry(trials[x]), x) def test_op_path_symmetry1(self): bscale = self.cscale.T(11) self.fulltest(self.cscale, bscale, [11], [3]) def test_op_path_symmetry2(self): d7b5 = self.c7b5.T(2) self.fulltest(self.c7b5, d7b5, [2, 8], [0, 6]) def test_op_path_symmetry3(self): baug = self.caug.T(11) self.fulltest(self.caug, baug, [3, 7, 11], [3, 7, 11]) def test_op_path_symmetry4(self): self.fulltest(self.dim, self.dim.T(1), [1, 4, 7, 10], [1, 4, 7, 10]) def test_rel_Tn(self): self.assert_(rel_Tn(self.cmaj, self.amaj)) def test_rel_TnI(self): self.assert_(rel_TnI(self.cmaj, self.cmin))
def test_minconf_neighbor1(self): # Tests neighbor conflict in an ordered set, part 1. pcs = PcSet('AB9') answer = 'A# B A' # 1 conflict. # 'Bb B A' also has 1 conflict, but A is not neighboring. # Therefore B pushes Bb to A#, a less popular note. self.assertEqual(notes(pcs), answer)
class SetRelationships(unittest.TestCase): def setUp(self): self.cmaj = PcSet('047') self.caug = PcSet('048') self.cscale = PcSet('024579B') self.blackkeys = self.cscale.complement() self.c7 = PcSet('047A') def test_is_complement(self): self.assert_(is_complement(self.cscale, self.blackkeys)) def test_is_prime_complement(self): mixedup = self.blackkeys.TnI(3) self.failIf(is_complement(self.cscale, mixedup)) self.assert_(is_prime_complement(self.cscale, mixedup)) def test_subset_of(self): self.assert_(subset_of(self.cscale, self.cmaj)) def test_prime_subset_of(self): self.failIf(subset_of(self.cscale, self.blackkeys)) self.assert_(prime_subset_of(self.cscale, self.blackkeys)) def test_not_prime_subset(self): self.failIf(prime_subset_of(self.cscale, self.caug)) def test_fit_in_1(self): result = fit_in(self.cscale, self.cmaj) self.assertEqual(result.Tn, [0, 5, 7]) self.assertEqual(result.TnI, [4, 9, 11]) def test_harmonize_1(self): result = harmonize(self.cscale, self.cmaj) self.assertEqual(result.Tn, [0, 5, 7]) self.assertEqual(result.TnI, [4, 9, 11]) def test_fit_in_2(self): result = fit_in(self.cscale, self.c7) self.assertEqual(result.Tn, [7]) self.assertEqual(result.TnI, [9]) def test_harmonize_2(self): result = harmonize(self.cscale, self.c7) self.assertEqual(result.Tn, [5]) self.assertEqual(result.TnI, [9]) # added Opset.__str__() in 2.0.0b3 def test_OpSet_string_1(self): result = fit_in(self.cscale, self.c7) self.assertEqual(str(result), 'T(7) T(9)I') def test_OpSet_string_2(self): result = harmonize(self.cscale, self.c7) self.assertEqual(str(result), 'T(5) T(9)I') def test_OpSet_string_3(self): # An augmented triad can't fit in the major scale. result = fit_in(self.cscale, self.caug) self.assertEqual(str(result), 'None')
def test_minconf_inescapable3(self): # 1 conflict no matter what. pcs = PcSet('78AB') answer = 'G Ab Bb B' # Similar to test above. # Screening against double accidental 'Ab A#' self.assertEqual(notes(pcs), answer)
def test_minconf_inescapable2(self): # 1 conflict no matter what. pcs = PcSet('5689') answer = 'F F# G# A' # Similar to test above. # Screening against double accidental 'Gb G#' self.assertEqual(notes(pcs), answer)
def test_minconf_inescapable1(self): # 1 conflict no matter what. pcs = PcSet('0134') answer = 'C Db Eb E' # 'C C# D# E' also valid, but not as popular. # 'C Db D# E' also technically valid, but double accidental ugly. # Worst answer = 'C C# Eb E' (2 conflicts) self.assertEqual(notes(pcs), answer)
def test_complement(self): """ Tests the principle that the union of the original set and its complement should be the chromatic set. """ fsm5 = self.amaj.complement() self.assertEqual(len(fsm5) + len(self.amaj), 12) chromatic = PcSet(list(self.amaj) + list(fsm5)) self.assertEqual(len(chromatic), 12)
def setUp(self): self.cscale = PcSet("024579B") self.ionian = PcSet("024579B") self.phrygian = PcSet("4579B02") self.jazzminor = PcSet("023579B") self.majortriad = PcSet("047") self.minortriad = PcSet("037") self.diminished = PcSet("0235689B")
class Similarity(unittest.TestCase): def setUp(self): self.a = PcSet('9047B2') self.b = PcSet('047B25') self.c = self.b.TnI(9) self.d = PcSet('9048AB') self.forte42 = PcSet([0, 1, 2, 4]) self.forte413 = PcSet([0, 1, 3, 6]) self.forte43 = PcSet([0, 1, 3, 4]) self.forte510 = PcSet([0, 1, 3, 4, 6]) self.forte5Z12 = PcSet([0, 1, 3, 5, 6]) self.forte5Z36 = PcSet([0, 1, 2, 4, 7]) def test_Rp_yes(self): self.assert_(Rp(self.a, self.b)) def test_Rp_no(self): self.failIf(Rp(self.a, self.c)) def test_Rp_prime_yes(self): self.assert_(Rp_prime(self.a, self.c)) def test_Rp_path(self): result = Rp_path(self.a, self.c) self.assertEqual(result.Tn, [5, 10]) self.assertEqual(result.TnI, [4, 9]) def test_Rp_prime_no(self): self.failIf(Rp_prime(self.a, self.d)) def test_R0_yes(self): self.assert_(R0(self.forte42, self.forte413)) def test_R0_no(self): self.failIf(R0(self.forte42, self.forte43)) def test_R1_yes(self): self.assert_(R1(self.forte42, self.forte43)) def test_R1_no(self): self.failIf(R1(self.forte42, self.forte413)) def test_R2_yes(self): self.assert_(R2(self.forte510, self.forte5Z12)) def test_R2_no_actually_R0(self): self.failIf(R2(self.forte42, self.forte413)) def test_R2_no_actually_R1(self): self.failIf(R2(self.forte42, self.forte43)) def test_Zpair_yes(self): self.assert_(Zpair(self.forte5Z12, self.forte5Z36)) def test_Zpair_no(self): self.failIf(Zpair(self.forte5Z12, self.forte510))
class FundamentalMethods(unittest.TestCase): def setUp(self): self.pcs = PcSet('0146') # These also test the __iter__ method, indirectly def test_inverse(self): """ Test the principle that, for a given pcset, the sum of the corresponding elements in the original and the inverse will always be 0 (in mod 12 arithmetic). """ inv = self.pcs.invert() self.assertEqual(len(self.pcs), len(inv)) for n, i in zip(self.pcs, inv): self.assertEqual((n + i) % 12, 0) def test_transpose(self): """ Tests the principle that, for a given pcset, the difference between the corresponding element in the original and the transposed version will always be equal to the transposition amount (in mod 12 arithmetic). """ for x in range(12): trx = self.pcs.transpose(x) self.assertEqual(len(self.pcs), len(trx)) for n, t in zip(self.pcs, trx): self.assertEqual((t - n) % 12, x % 12) def test_transpose_float(self): trf = self.pcs.transpose(3.6) for n, t in zip(self.pcs, trf): self.assertEqual((t - n) % 12, 3) def test_transpose_empty(self): es = PcSet([]) self.assertEqual(list(es.transpose(3)), [])
def test_from_string_get_len(self): pcs = PcSet(self.s) self.assertEqual(len(pcs), 7)
def setUp(self): self.a = PcSet([]) self.b = PcSet([]) self.chromo = PcSet(range(12))
def setUp(self): self.cmaj = PcSet('047') self.caug = PcSet('048') self.cscale = PcSet('024579B') self.blackkeys = self.cscale.complement() self.c7 = PcSet('047A')
def test_ivec_ait2(self): ait2 = PcSet('0137') self.assertEqual(ait2.ivec(), [1] * 6)
def test_ivec_ait1(self): ait1 = PcSet('0146') self.assertEqual(ait1.ivec(), [1] * 6)
def test_empty_list(self): pcs = PcSet([]) self.assertEqual(str(pcs), '')
def setUp(self): self.pcs = PcSet('0146')
def test_empty_string(self): pcs = PcSet('') self.assertEqual(list(pcs), [])
def test_convert_floats(self): pcs = PcSet([0, 1, 2.2, 3.1415]) self.assertEqual(list(pcs), [0, 1, 2, 3])
def test_remove_duplicates(self): pcs = PcSet('01AAAA') self.assertEqual(list(pcs), [0, 1, 10])
def test_from_list_to_string(self): pcs = PcSet(self.i) self.assertEqual(str(pcs), self.s)
def test_from_list_to_list(self): pcs = PcSet(self.i) self.assertEqual(list(pcs), self.i)
def setUp(self): self.cmaj = PcSet('047') self.amaj = PcSet('914') self.cmin = PcSet('037') self.caug = PcSet('048') # symmetry 3 self.cscale = PcSet('024579B') # symmetry 1 self.c7b5 = PcSet('046A') # symmetry 2 self.dim = PcSet('0369') # symmetry 4
def test_from_list_get_len(self): pcs = PcSet(self.i) self.assertEqual(len(pcs), 7)