User:Arseniiv/Fitting: Difference between revisions

Arseniiv (talk | contribs)
Arseniiv (talk | contribs)
m Code: a link to a gist
 
(One intermediate revision by the same user not shown)
Line 28: Line 28:


==== Code ====
==== Code ====
''NB. This code may later be lagging behind [https://gist.github.com/arseniiv/ab128927adc3955867c1cc1bfe6b4cd7 the version at Gist]. The version there is a self-contained module with an example like one in this article.''


Should work in Python 3.12 and several previous versions. Install fresh <code>more_itertools</code> and <code>sympy</code>.
Should work in Python 3.12 and several previous versions. Install fresh <code>more_itertools</code> and <code>sympy</code>.
Line 40: Line 42:
import sympy as sp
import sympy as sp


def cents(ratio: float | str) -> float:
def _cents(ratio: float | str) -> float:
     if isinstance(ratio, str):
     if isinstance(ratio, str):
         ratio = float(Fraction(ratio))
         ratio = float(Fraction(ratio))
Line 48: Line 50:
     """Make a scale of pitches in cents from intervals delimited by spaces."""
     """Make a scale of pitches in cents from intervals delimited by spaces."""


     return tuple(map(cents, intervals.split()))
     return tuple(map(_cents, intervals.split()))


def match_pattern(scale: Sequence[float], pattern: str) -> dict[str, float] | None:
def match_pattern(scale: Sequence[float], pattern: str) -> dict[str, float] | None:
Line 88: Line 90:
     note_errors = [vars_[SHIFT]]
     note_errors = [vars_[SHIFT]]
     sym_pitches = [sp.sympify(0)]
     sym_pitches = [sp.sympify(0)]
     for letter, pitch in zip(pattern, initial_scale):
     for letter, pitch in zip(pattern, scale):
         last_pitch = sym_pitches[-1] + vars_[letter]
         last_pitch = sym_pitches[-1] + vars_[letter]
         sym_pitches.append(last_pitch)
         sym_pitches.append(last_pitch)
Line 96: Line 98:
     note_errors.pop()
     note_errors.pop()
     sym_pitches.pop(0)
     sym_pitches.pop(0)
     assert len(note_errors) == len(initial_scale)
     assert len(note_errors) == len(scale)


     error_sqr_sum = sum(error ** 2 for error in note_errors)
     error_sqr_sum = sum(error ** 2 for error in note_errors)