def transformChunk(chunk, prev_note, chords):
    # get list of transform functions
    appropriate_function_list = ["identity", "partialTranspose", "retrograde", "partialRetrograde", "subRhythm"]
    functions_list = dict(
        [(o[0], o[1]) for o in getmembers(tfs) if isfunction(o[1])]
    )  # list of all possible transform functions
    functions_list = dict(filter(lambda i: i[0] in appropriate_function_list, functions_list.items()))
    functions_names = functions_list.keys()
    random.shuffle(functions_names)
    have_chunk = False  # haven't created new cell yet
    i = 0
    while not have_chunk and i < len(appropriate_function_list):  # loop until appropriate cell is found
        if chunk.depth == 2:
            print(functions_names[i])
        if chunk.depth <= 1:
            new_variations = functions_list[functions_names[i]](chunk, chords, prev_note)
        elif chunk.depth == 2:
            new_variations = thp.mapToHPhrase(functions_list[functions_names[i]], chunk, chords, prev_note)
        random.shuffle(new_variations)
        for variation in new_variations:
            if pref.fitsPref(variation, prev_note, chords):
                return variation
        i += 1
    if chunk.depth == 0:
        return gc.getCell(2, prev_note, None, chords[0], chunk.durs, chunk.ctype)
    elif chunk.depth == 1:
        cell1 = gc.getCell(2, prev_note, None, chords[0], chunk.sub_chunks[0].durs, chunk.sub_chunks[0].ctype)
        cell2 = transformChunk(cell1, cell1.pits[-1], [chords[1]])
        return Chunk([cell1, cell2])
    else:
        print("sucker")
        motif1 = genMotif(prev_note, chords[0:2])
        motif2 = transformChunk(motif1, motif1.pits[-1], chords[2:])
        return Chunk([motif1, motif2])
def genMotif(prev_note=0, harmony=[[0, 2, 4], [4, 6, 8]]):
    first_chord = harmony[0]
    second_chord = harmony[1]
    # gen first cell
    cell1 = gc.getCell(2, prev_note, None, first_chord, [])
    # either gen or transform second cell
    next_cell_type = ph.probDictToChoice({"transformed": 0.7, "new": 0.3})
    if len(set(cell1.durs)) < 2 and len(cell1.durs) > 1:
        next_cell_type = "new"
    if next_cell_type == "new":
        cell2 = gc.getCell(2, cell1.pits[-1], None, second_chord, [])
    else:
        cell2 = transformChunk(cell1, cell1.pits[-1], [second_chord])
    return Chunk([cell1, cell2])
def transformCell(cell, harm, prev_note = None):
    if prev_note == None:
        prev_note = cell.pits[-1]
    transformed_already = []
    for function in appropriate_function_list:
        new_cells = functions_list[function](cell, prev_note)
        random.shuffle(new_cells)
        transformed_already.append(new_cells[0])
        """for new_cell in new_cells:
            for harmony in harm:
                if hm.chunkInChord(new_cell, harmony) and pref.fitsPref(new_cell, prev_note, harmony):
                    return new_cell"""
    #now try transforming already transformed cells
    for transformed_once in transformed_already:
        for function in appropriate_function_list:
            new_cells = functions_list[function](transformed_once, prev_note)
            random.shuffle(new_cells)
            for new_cell in new_cells:
                for harmony in harm:
                    if hm.chunkInChord(new_cell, harmony) and pref.fitsPref(new_cell, prev_note,harmony):
                        if random.uniform(0,1) < 0.8:
                            return random.choice(tfs.subRhythm(new_cell, prev_note, harmony, how_many=1))
                        else:
                            return new_cell
    return gc.getCell(2, prev_note, first_note = None, chord = harm[0], durs = cell.durs)
def genMotif(prev_note = 0, harm = [tuple([[0,2,4]]), ([0,2,4], [4,6,8])], nameA = 'cell', nameB = 'cell', name = 'motif', names = {}):
    #print('harm = ' + str(harm))
    #print('harm[0] = ' + str(harm[0]))
    #print('harm[0][0] ' + str(harm[0][0]))
    cell1 = gc.getCell(length=2, prev_note=prev_note, first_note = None, chord=harm[0][0], durs=[])
    cell1.name = getName(names, nameB)
    prev_note = cell1.pits[-1]
    cell2 = transformCell(cell1, harm[1], prev_note=prev_note)
    cell2.name = getName(names, nameB)
    if fitsMotifPref([cell1, cell2]):
        new_subs = OrderedDict()
        new_subs[cell1.name] = cell1
        new_subs[cell2.name] = cell2
        if cell1.name in names:
            names[cell1.name] += 1
        if cell2.name in names:
            names[cell2.name] += 1
        new_chunk = Chunk(sub_chunks = new_subs, name = getName(names, name))
        return (new_chunk, names)
    else:
        return genMotif(prev_note, harm, nameA, nameB, names=names)