Example #1
0
def tonal_space_distance(sem1, sem2):
    """
    Computes the edit distance between the tonal space paths of two logical 
    forms, using a suitable scoring. This uses a cost of 2 for deletions and 
    insertions and scores 1 for a substitution that gets either 
    the step or function right, but not both. The result is then 
    divided by 2 (meaning that effectively all costs are 1 and a 0.5 
    cost is given to half-right substitutions).
    
    The alignment is not between the tonal space points themselves, but 
    between the vectors between each pair of points (that is the points 
    relative to the previous point). This means that a path won't be 
    penalised if part of it is translated by a constant vector, except at 
    the point where it goes wrong.
    
    """
    from jazzparser.utils.distance import levenshtein_distance
    # Get a list of (coord,fun) pairs for the logical forms
    seq1 = _lf_to_coord_funs(sem1)
    seq2 = _lf_to_coord_funs(sem2)
    # Produce a version of the paths made up of steps and functions,
    #  rather than points and functions
    steps1 = _steps_list(seq1)
    steps2 = _steps_list(seq2)

    edit_dist = levenshtein_distance(steps1,
                                     steps2,
                                     delins_cost=2,
                                     subst_cost_fun=_subst_cost)
    return float(edit_dist) / 2.0
Example #2
0
def tonal_space_distance(sem1, sem2):
    """
    Computes the edit distance between the tonal space paths of two logical 
    forms, using a suitable scoring. This uses a cost of 2 for deletions and 
    insertions and scores 1 for a substitution that gets either 
    the step or function right, but not both. The result is then 
    divided by 2 (meaning that effectively all costs are 1 and a 0.5 
    cost is given to half-right substitutions).
    
    The alignment is not between the tonal space points themselves, but 
    between the vectors between each pair of points (that is the points 
    relative to the previous point). This means that a path won't be 
    penalised if part of it is translated by a constant vector, except at 
    the point where it goes wrong.
    
    """
    from jazzparser.utils.distance import levenshtein_distance
    # Get a list of (coord,fun) pairs for the logical forms
    seq1 = _lf_to_coord_funs(sem1)
    seq2 = _lf_to_coord_funs(sem2)
    # Produce a version of the paths made up of steps and functions, 
    #  rather than points and functions
    steps1 = _steps_list(seq1)
    steps2 = _steps_list(seq2)
    
    edit_dist = levenshtein_distance(
                                steps1, 
                                steps2,
                                delins_cost=2,
                                subst_cost_fun=_subst_cost)
    return float(edit_dist) / 2.0
Example #3
0
def chord_sequence_match_score(seq1, seq2):
    """
    Computes the edit distance between two chord sequences to score the 
    extent of the matching between the two sequences between 0 and 1.
    
    Each sequence should be a list of L{jazzparser.data.db_mirrors.Chord}s.
    The metric is key-independent. The distance will be tried for every 
    transposition of one of the sequences and the closest match will be 
    used.
    
    """
    costs = []
    for transpose in range(12):
        # Give a half-point to alignments of roots without labels or vice versa
        def _subst_cost(crd1, crd2):
            cost = 0
            if (crd1.root + transpose) % 12 == crd2.root:
                cost += -1
            if crd1.type == crd2.type:
                cost += -1
            return cost

        # Try aligning the two sequences
        align_cost = levenshtein_distance(seq1,
                                          seq2,
                                          delins_cost=0,
                                          subst_cost_fun=_subst_cost)
        costs.append((transpose, align_cost))

    transposition, align_cost = min(costs, key=lambda x: x[1])
    align_score = float(-align_cost) / 2

    # Compute f-score of optimal alignment
    precision = align_score / len(seq1)
    recall = align_score / len(seq2)
    f_score = 2.0 * precision * recall / (precision + recall)

    return f_score, transposition
Example #4
0
def chord_sequence_match_score(seq1, seq2):
    """
    Computes the edit distance between two chord sequences to score the 
    extent of the matching between the two sequences between 0 and 1.
    
    Each sequence should be a list of L{jazzparser.data.db_mirrors.Chord}s.
    The metric is key-independent. The distance will be tried for every 
    transposition of one of the sequences and the closest match will be 
    used.
    
    """
    costs = []
    for transpose in range(12):
        # Give a half-point to alignments of roots without labels or vice versa
        def _subst_cost(crd1, crd2):
            cost = 0
            if (crd1.root+transpose) % 12 == crd2.root:
                cost += -1
            if crd1.type == crd2.type:
                cost += -1
            return cost
        
        # Try aligning the two sequences
        align_cost = levenshtein_distance(seq1, seq2, 
                                          delins_cost=0, 
                                          subst_cost_fun=_subst_cost)
        costs.append((transpose,align_cost))
    
    transposition, align_cost = min(costs, key=lambda x:x[1])
    align_score = float(-align_cost) / 2
    
    # Compute f-score of optimal alignment
    precision = align_score / len(seq1)
    recall = align_score / len(seq2)
    f_score = 2.0 * precision * recall / (precision+recall)
    
    return f_score,transposition