tonos

Tonos handles all aspects of pitch and harmonic material including individual tones, pitch collections, scales, chords, harmonic systems and spaces, interval relationships, and frequency-based transformations.

Pitch

Pitch Core

class klotho.tonos.pitch.pitch.Pitch(pitch_input=None, octave=4, cents_offset=0.0, partial=1)[source]

Bases: object

A musical pitch with frequency, pitch class, octave, and partial information.

Pitch represents a specific musical frequency with associated metadata including pitch class name, octave number, cents offset from equal temperament, and partial number for harmonic series calculations.

Parameters:
  • pitch_input (str or None, optional) – Pitch class name (e.g., "C", "F#") or pitch with octave (e.g., "C4", "Bb-1").

  • octave (int, optional) – Octave number. Default is 4 (middle octave).

  • cents_offset (float, optional) – Deviation from equal temperament in cents. Default is 0.0.

  • partial (int, float, or Fraction, optional) – Partial number or frequency ratio. Default is 1 (fundamental).

Examples

>>> p = Pitch("C4")
>>> p.freq
261.6255653005986
>>> p = Pitch("A", 4, 0.0)
>>> p.freq
440.0
>>> p = Pitch("C", 4, 14.0)
>>> p.cents_offset
14.0
>>> p = Pitch.from_freq(880.0)
>>> str(p)
'A5'
__init__(pitch_input=None, octave=4, cents_offset=0.0, partial=1)[source]
classmethod from_freq(freq, partial=1)[source]

Create a Pitch from a frequency in Hertz.

Parameters:
  • freq (float) – Frequency in Hertz.

  • partial (int, float, or Fraction, optional) – Partial number or frequency ratio. Default is 1.

Returns:

A new Pitch instance corresponding to the given frequency.

Return type:

Pitch

classmethod from_midi(midi_note, partial=1)[source]

Create a Pitch from a MIDI note number.

Parameters:
  • midi_note (float) – MIDI note number (e.g., 60 for middle C, 69 for A4).

  • partial (int, float, or Fraction, optional) – Partial number or frequency ratio. Default is 1.

Returns:

A new Pitch instance corresponding to the MIDI note.

Return type:

Pitch

classmethod from_midicent(midicent_value, partial=1)[source]

Create a Pitch from a MIDI cent value.

Parameters:
  • midicent_value (float) – MIDI cent value (e.g., 6900 for A4).

  • partial (int, float, or Fraction, optional) – Partial number or frequency ratio. Default is 1.

Returns:

A new Pitch instance corresponding to the MIDI cent value.

Return type:

Pitch

property pitchclass

The pitch class name (e.g., 'C', 'F#').

Type:

str

property octave

The octave number.

Type:

int

property cents_offset

Deviation from equal temperament in cents.

Type:

float

property partial

The partial number or frequency ratio.

Type:

int, float, or Fraction

property freq

The frequency in Hertz.

Type:

float

property midicent

The MIDI cent representation of this pitch.

Type:

float

property midi

The MIDI note number, rounded when cents offset is negligible.

Type:

float

property virtual_fundamental

The implied fundamental derived from this pitch’s partial number.

Type:

Pitch

is_same_note(other)[source]

Check whether two pitches share the same pitch class and octave.

Parameters:

other (Pitch) – The pitch to compare against.

Returns:

True if both pitch class and octave match.

Return type:

bool

is_same_pitchclass(other)[source]

Check whether two pitches share the same pitch class regardless of octave.

Parameters:

other (Pitch) – The pitch to compare against.

Returns:

True if pitch classes match.

Return type:

bool

cents_difference(other)[source]

Calculate the interval between this pitch and another in cents.

Parameters:

other (Pitch) – The pitch to measure the interval to.

Returns:

Signed interval in cents (positive if self is higher).

Return type:

float

Raises:

TypeError – If other is not a Pitch instance.

with_partial(partial)[source]

Return a copy of this pitch with a different partial number.

Parameters:

partial (int, float, or Fraction) – The new partial number to assign.

Returns:

A new Pitch sharing all attributes except the partial.

Return type:

Pitch

Pitch Collections

class klotho.tonos.pitch.pitch_collections.PitchCollectionBase[source]

Bases: ABC

Abstract base class for all pitch collections.

Defines the common interface for both relative (interval-based) and absolute (pitch-based) collections, including properties for degrees, pitches, intervals, equave, and indexing operations.

abstract property is_relative: bool
abstract property is_instanced: bool
abstract property reference_pitch: Pitch | None
abstract property equave: float | Fraction
abstract property equave_cyclic: bool
abstract property degrees: List[Pitch | float | Fraction]
abstract property pitches: List[Pitch]
abstract property intervals: List[float | Fraction]
index(value, start=0, stop=None)[source]

Return the index of the first occurrence of value in the collection.

Parameters:
  • value (Pitch, float, Fraction, int, or str) – The value to search for. Interpreted as a degree for relative collections without a reference pitch, or as a Pitch otherwise.

  • start (int, optional) – Index at which to begin the search. Default is 0.

  • stop (int or None, optional) – Index at which to stop searching. Default is None (end).

Returns:

The index of the matching element.

Return type:

int

Raises:

ValueError – If the value is not found in the collection.

class klotho.tonos.pitch.pitch_collections.EquaveCyclicMixin[source]

Bases: object

Mixin that enables equave-cyclic indexing by default.

class klotho.tonos.pitch.pitch_collections.RelativePitchCollection(degrees, interval_type='ratios', equave=None, reference_pitch=None)[source]

Bases: PitchCollectionBase

A collection of pitches defined by interval degrees relative to a root.

Degrees are stored as ratios (Fraction) or cents (float) and can optionally be anchored to a reference pitch to resolve concrete Pitch objects. Supports equave-cyclic indexing when enabled.

Parameters:
  • degrees (list of float, Fraction, int, or str) – Scale/chord degrees as ratios or cent values.

  • interval_type (str, optional) – "ratios" or "cents". Default is "ratios".

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence. When provided, equave-cyclic indexing is enabled.

  • reference_pitch (Pitch, str, or None, optional) – If given, the collection is instanced at this pitch and indexing returns Pitch objects.

Examples

>>> coll = RelativePitchCollection(["1/1", "5/4", "3/2"])
>>> coll.degrees
[Fraction(1, 1), Fraction(5, 4), Fraction(3, 2)]
__init__(degrees, interval_type='ratios', equave=None, reference_pitch=None)[source]
classmethod from_degrees(degrees, interval_type='ratios', equave=None, reference_pitch=None)[source]

Construct from an explicit list of cumulative degrees.

Parameters:
  • degrees (list) – Cumulative degree values (ratios or cents).

  • interval_type (str, optional) – "ratios" or "cents".

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

Return type:

RelativePitchCollection

classmethod from_intervals(intervals, interval_type='ratios', equave=None, reference_pitch=None)[source]

Construct from successive intervals (step sizes) rather than cumulative degrees.

Parameters:
  • intervals (list) – Successive interval values (ratios or cents).

  • interval_type (str, optional) – "ratios" or "cents".

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

Return type:

RelativePitchCollection

classmethod from_setclass(pcs, mod=12, equave=None, reference_pitch=None)[source]

Construct from pitch-class integers in an equal-tempered system.

Parameters:
  • pcs (list of int) – Pitch-class integers (e.g., [0, 4, 7] for a major triad in 12-TET).

  • mod (int, optional) – Number of divisions per equave. Default is 12.

  • equave (float, Fraction, int, str, or None, optional) – Override equave in cents. Defaults to mod * 100.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

Return type:

RelativePitchCollection

property is_relative: bool

Always True for relative collections.

Type:

bool

property is_instanced: bool

True if a reference pitch has been assigned.

Type:

bool

property reference_pitch: Pitch | None

The reference pitch anchoring the collection.

Type:

Pitch or None

property equave: float | Fraction

The interval of equivalence.

Type:

float or Fraction

property equave_cyclic: bool

Whether indexing wraps around the equave.

Type:

bool

property degrees: List[float | Fraction]

The cumulative degree values (ratios or cents).

Type:

list

property pitches: List[Pitch]

Concrete pitches resolved from degrees and reference pitch.

Raises:

ValueError – If no reference pitch has been set.

Type:

list of Pitch

property intervals: List[float | Fraction]

Successive intervals between adjacent degrees.

Type:

list

property interval_type: type | None

The Python type of the stored degrees (float or Fraction).

Type:

type or None

root(pitch)[source]

Return a copy of this collection rooted at the given pitch.

Parameters:

pitch (Pitch or str) – The pitch to use as the reference root.

Return type:

RootedPitchCollection

relative()[source]

Return a rootless copy retaining only the interval structure.

Return type:

RelativePitchCollection

class klotho.tonos.pitch.pitch_collections.RootedPitchCollection(degrees, interval_type='ratios', equave=None, reference_pitch=None)[source]

Bases: RelativePitchCollection

A RelativePitchCollection that always carries a reference pitch.

Slicing or sequence-indexing a RelativePitchCollection with a reference pitch produces a RootedPitchCollection so that the root information is preserved through subsetting.

root(pitch)[source]

Return a copy rooted at a different pitch.

Parameters:

pitch (Pitch or str) – The new reference pitch.

Return type:

RootedPitchCollection

relative()[source]
Return type:

RelativePitchCollection

class klotho.tonos.pitch.pitch_collections.AbsolutePitchCollection(pitches, equave=None, reference_pitch=None)[source]

Bases: PitchCollectionBase

A collection defined by concrete Pitch objects rather than intervals.

Intervals are derived from successive pitch frequencies rather than stored directly. Supports equave-cyclic indexing when an equave is provided.

Parameters:
  • pitches (list of Pitch or str) – The pitches in the collection.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence for cyclic indexing.

  • reference_pitch (Pitch, str, or None, optional) – Optional reference pitch for partial calculations.

__init__(pitches, equave=None, reference_pitch=None)[source]
property is_relative: bool

Always False for absolute collections.

Type:

bool

property is_instanced: bool

True if a reference pitch has been assigned.

Type:

bool

property reference_pitch: Pitch | None

The reference pitch.

Type:

Pitch or None

property equave: float | Fraction

The interval of equivalence.

Type:

float or Fraction

property equave_cyclic: bool

Whether indexing wraps around the equave.

Type:

bool

property degrees: List[Pitch]

The pitches (same as pitches for absolute collections).

Type:

list of Pitch

property pitches: List[Pitch]

The stored pitch objects.

Type:

list of Pitch

property intervals: List[float]

Successive intervals in cents between adjacent pitches.

Type:

list of float

root(pitch)[source]

Return a copy with a different reference pitch.

Parameters:

pitch (Pitch or str) – The new reference pitch.

Return type:

AbsolutePitchCollection

class klotho.tonos.pitch.pitch_collections.PitchCollection[source]

Bases: object

Factory class providing unified constructors for pitch collections.

All methods are classmethods that delegate to RelativePitchCollection or AbsolutePitchCollection depending on the input format. Use this class when you want a single entry point for creating collections from degrees, intervals, set classes, pitches, MIDI notes, MIDI cents, or frequencies.

classmethod from_degrees(degrees, mode='ratios', equave=None, reference_pitch=None, mod=12)[source]

Create a relative collection from cumulative degree values.

Parameters:
  • degrees (list) – Degree values as ratios, cents, or pitch-class integers.

  • mode (str, optional) – "ratios", "cents", or "setclass". Default is "ratios".

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

  • mod (int, optional) – Divisions per equave when mode is "setclass". Default is 12.

Return type:

RelativePitchCollection

classmethod from_intervals(intervals, mode='ratios', equave=None, reference_pitch=None, mod=12)[source]

Create a relative collection from successive interval sizes.

Parameters:
  • intervals (list) – Successive interval values.

  • mode (str, optional) – "ratios", "cents", or "setclass". Default is "ratios".

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

  • mod (int, optional) – Divisions per equave when mode is "setclass". Default is 12.

Return type:

RelativePitchCollection

classmethod from_setclass(pcs, mod=12, equave=None, reference_pitch=None)[source]

Create a relative collection from pitch-class integers.

Parameters:
  • pcs (list of int) – Pitch-class integers.

  • mod (int, optional) – Divisions per equave. Default is 12.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

Return type:

RelativePitchCollection

classmethod from_pitch(pitches, equave=None, reference_pitch=None)[source]

Create an absolute collection from Pitch objects or pitch strings.

Parameters:
  • pitches (list of Pitch or str) – The pitches to include.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence for cyclic indexing.

  • reference_pitch (Pitch, str, or None, optional) – Optional reference pitch.

Return type:

AbsolutePitchCollection

classmethod from_midi(midi_notes, equave=None, reference_pitch=None)[source]

Create an absolute collection from MIDI note numbers.

Parameters:
  • midi_notes (list of float) – MIDI note numbers.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional reference pitch.

Return type:

AbsolutePitchCollection

classmethod from_midicent(midicents, equave=None, reference_pitch=None)[source]

Create an absolute collection from MIDI cent values.

Parameters:
  • midicents (list of float) – MIDI cent values.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional reference pitch.

Return type:

AbsolutePitchCollection

classmethod from_freq(frequencies, equave=None, reference_pitch=None)[source]

Create an absolute collection from frequencies in Hertz.

Parameters:
  • frequencies (list of float) – Frequencies in Hertz.

  • equave (float, Fraction, int, str, or None, optional) – Interval of equivalence.

  • reference_pitch (Pitch, str, or None, optional) – Optional reference pitch.

Return type:

AbsolutePitchCollection

Contour

class klotho.tonos.pitch.contour.Contour(values)[source]

Bases: object

A pitch contour represented as a 1-D numpy array of integers.

Contour provides element-wise arithmetic operations and an outer sum method for Cartesian sum (chord multiplication). All operations return new Contour instances (immutable design).

A contour represents the shape of pitch motion as a sequence of scale degree indices. It can be used to index into pitch collections (Scale, Chord, etc.) to retrieve actual pitches.

Parameters:

values (list of int, Sequence, numpy.ndarray, or Contour) – Sequence of integers representing the contour.

Examples

>>> contour = Contour([6, 2, 4, 0])
>>> contour + 1
Contour([7, 3, 5, 1])
>>> contour * 2
Contour([12, 4, 8, 0])
>>> contour + Contour([1, 2, 3, 4])
Contour([7, 4, 7, 4])
>>> Contour.outer([6, 2, 4, 0], [0, 3, 1])
Contour([6, 9, 7, 2, 5, 3, 4, 7, 5, 0, 3, 1])
__init__(values)[source]
classmethod outer(a, b)[source]

Compute the outer sum (Cartesian sum) of two sequences.

Also known as “chord multiplication” in set-theoretic music theory (Boulez). For each element in a, adds all elements of b, returning a flattened result.

Parameters:
Returns:

New Contour containing the flattened outer sum.

Return type:

Contour

Examples

>>> Contour.outer([0, 1, 2], [4, 0])
Contour([4, 0, 5, 1, 6, 2])
>>> Contour.outer(Contour([6, 2, 4, 0]), [0, 3, 1])
Contour([6, 9, 7, 2, 5, 3, 4, 7, 5, 0, 3, 1])
classmethod concat(contours)[source]

Concatenate multiple contours into one flat contour.

Parameters:

contours (list of Contour) – Contour instances to concatenate.

Returns:

New Contour containing all values in sequence.

Return type:

Contour

Examples

>>> c1 = Contour([0, 2, 4])
>>> c2 = Contour([1, 3, 5])
>>> Contour.concat([c1, c2])
Contour([0, 2, 4, 1, 3, 5])
property values: List[int]

The contour values as a Python list.

Type:

list of int

__mod__(other)[source]

Musical modulo operation that preserves sign.

Unlike standard Python mod which always returns non-negative values, this preserves the sign of the input to maintain musical semantics where negative indices indicate pitches below the root.

Return type:

Contour

Examples

>>> Contour([13, -13, -1, -12, 0]) % 12
Contour([1, -1, -1, 0, 0])
copy()[source]

Return a copy of this contour.

Return type:

Contour

invert(axis=0)[source]

Return an inverted copy reflected around axis.

Uses the formula 2 * axis - value. With the default axis=0 this is equivalent to negation.

Parameters:

axis (int, optional) – The pitch value to reflect around. Default is 0.

Returns:

New Contour with inverted values.

Return type:

Contour

retrograde()[source]

Return the retrograde (reversed order) of this contour.

Return type:

Contour

rotate(n)[source]

Circular shift of contour values.

Parameters:

n (int) – Number of positions to shift. Positive shifts right, negative shifts left.

Returns:

New Contour with rotated values.

Return type:

Contour

Examples

>>> Contour([0, 1, 2, 3]).rotate(1)
Contour([3, 0, 1, 2])
>>> Contour([0, 1, 2, 3]).rotate(-1)
Contour([1, 2, 3, 0])
normalized(start=0)[source]

Shift contour so the minimum value equals start.

Parameters:

start (int, optional) – The value that the minimum should equal. Default is 0.

Returns:

New Contour shifted so that its minimum equals start.

Return type:

Contour

Examples

>>> Contour([5, 3, 7, 4]).normalized()
Contour([2, 0, 4, 1])
>>> Contour([5, 3, 7, 4]).normalized(1)
Contour([3, 1, 5, 2])
zeroed(start=0)[source]

Shift contour so the first value equals start.

Parameters:

start (int, optional) – The value that the first element should equal. Default is 0.

Returns:

New Contour with values shifted relative to the first element.

Return type:

Contour

Examples

>>> Contour([5, 3, 7, 4]).zeroed()
Contour([0, -2, 2, -1])
>>> Contour([5, 3, 7, 4]).zeroed(1)
Contour([1, -1, 3, 0])
to_numpy()[source]

Return a copy of the internal numpy array.

Return type:

numpy.ndarray

Scales

Scale Implementation

class klotho.tonos.scales.scale.Scale(degrees=['1/1', '9/8', '5/4', '4/3', '3/2', '5/3', '15/8'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]

Bases: EquaveCyclicMixin, RelativePitchCollection

A musical scale with automatic sorting, deduplication, and equave reduction.

Scale represents a collection of pitch intervals that form a musical scale. It automatically sorts degrees, removes duplicates, equave-reduces intervals, and ensures the unison (1/1 or 0 cents) is present. Scales always use equave-cyclic indexing for accessing pitches in different octaves.

Parameters:
  • degrees (list of str, float, int, or Fraction) – Intervals as ratios (e.g., "5/4"), decimals, or numbers.

  • interval_type (str, optional) – "ratios" or "cents". Default is "ratios".

  • equave (float, Fraction, int, or str, optional) – Interval of equivalence. Default is "2/1" (octave).

  • reference_pitch (Pitch, str, or None, optional) – If provided, the scale is instanced at this pitch.

Examples

>>> scale = Scale(["1/1", "9/8", "5/4", "4/3", "3/2", "5/3", "15/8"])
>>> scale.degrees
[Fraction(1, 1), Fraction(9, 8), Fraction(5, 4), Fraction(4, 3), Fraction(3, 2), Fraction(5, 3), Fraction(15, 8)]
>>> scale[7]
Fraction(2, 1)
>>> c_major = scale.root("C4")
>>> c_major[0]
Pitch(C4, 261.63 Hz)
__init__(degrees=['1/1', '9/8', '5/4', '4/3', '3/2', '5/3', '15/8'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]
property intervals: List[float | Fraction]

Successive step intervals including the closing interval to the equave.

Type:

list

property degrees: List[Pitch | float | Fraction]

Cumulative degrees. Returns Pitch objects when instanced.

Type:

list

relative()[source]

Return a rootless copy retaining only the interval structure.

Return type:

Scale

root(pitch)[source]

Return a copy of this scale rooted at the given pitch.

Parameters:

pitch (Pitch or str) – The reference pitch.

Return type:

Scale

mode(mode_number)[source]

Return a modal rotation of this scale.

Parameters:

mode_number (int) – Zero-based mode index. 0 returns the original scale, 1 starts from the second degree, etc.

Returns:

A new Scale whose degrees are rotated to begin on the specified degree of the original.

Return type:

Scale

classmethod n_edo(n=12, equave=1200.0, reference_pitch=None)[source]

Construct an equal-division-of-the-octave (EDO) scale.

Parameters:
  • n (int, optional) – Number of equal divisions. Default is 12.

  • equave (float, optional) – Size of the equave in cents. Default is 1200.0.

  • reference_pitch (Pitch, str, or None, optional) – Optional root pitch.

Return type:

Scale

classmethod ionian(reference_pitch=None)[source]
Return type:

Scale

classmethod dorian(reference_pitch=None)[source]
Return type:

Scale

classmethod phrygian(reference_pitch=None)[source]
Return type:

Scale

classmethod lydian(reference_pitch=None)[source]
Return type:

Scale

classmethod mixolydian(reference_pitch=None)[source]
Return type:

Scale

classmethod aeolian(reference_pitch=None)[source]
Return type:

Scale

classmethod locrian(reference_pitch=None)[source]
Return type:

Scale

classmethod bagpipes(reference_pitch=None)[source]
Return type:

Scale

classmethod janus(reference_pitch=None)[source]
Return type:

Scale

klotho.tonos.scales.scale.InstancedScale

alias of Scale

Chords

Chord Implementation

class klotho.tonos.chords.chord.Chord(degrees=['1/1', '5/4', '3/2'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]

Bases: EquaveCyclicMixin, RelativePitchCollection

A musical chord with automatic sorting and deduplication.

Chord represents a collection of pitch intervals that form a musical chord. It automatically sorts degrees, removes duplicates, and equave-reduces intervals, but unlike Scale, it does NOT enforce the presence of unison. Chords always use equave-cyclic indexing for accessing chord tones in different octaves.

Parameters:
  • degrees (list of str, float, int, or Fraction) – Intervals as ratios (e.g., "5/4"), decimals, or numbers.

  • interval_type (str, optional) – "ratios" or "cents". Default is "ratios".

  • equave (float, Fraction, int, or str, optional) – Interval of equivalence. Default is "2/1" (octave).

  • reference_pitch (Pitch, str, or None, optional) – If provided, the chord is instanced at this pitch.

Examples

>>> chord = Chord(["1/1", "5/4", "3/2"])
>>> chord.degrees
[Fraction(1, 1), Fraction(5, 4), Fraction(3, 2)]
>>> chord[3]
Fraction(2, 1)
>>> c_major = chord.root("C4")
>>> c_major[0]
Pitch(C4, 261.63 Hz)
__init__(degrees=['1/1', '5/4', '3/2'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]
property intervals: List[float | Fraction]

Successive intervals between adjacent chord tones.

Type:

list

property degrees: List[Pitch | float | Fraction]

Cumulative degrees. Returns Pitch objects when instanced.

Type:

list

relative()[source]

Return a rootless copy retaining only the interval structure.

Return type:

Chord

root(pitch)[source]

Return a copy of this chord rooted at the given pitch.

Parameters:

pitch (Pitch or str) – The reference pitch.

Return type:

Chord

normalized()[source]

Transpose the chord so the lowest degree is the unison (1/1 or 0 cents).

Return type:

Chord

voicing(index)[source]

Extract a Voicing from this chord by selecting tones with cyclic indexing.

Unlike slicing (which returns a RelativePitchCollection), this preserves multi-octave spread by using cyclic degree lookup without equave reduction.

Parameters:

index (int, slice, or sequence of int) – Indices into the chord (cyclic).

Return type:

Voicing

classmethod from_collection(collection, equave=None)[source]

Construct a Chord from an existing relative pitch collection.

Parameters:
  • collection (PitchCollectionBase) – A relative pitch collection to convert.

  • equave (float, Fraction, int, str, or None, optional) – Override equave. Defaults to the collection’s equave.

Return type:

Chord

Raises:

ValueError – If the collection is absolute (not relative).

class klotho.tonos.chords.chord.Voicing(degrees=['1/1', '5/4', '3/2'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]

Bases: RelativePitchCollection

A musical voicing with no equave reduction, removing only exact duplicates.

Voicing represents a “frozen” set of intervals that preserves exact pitch relationships without equave cycling. Unlike Chord, it does not reduce intervals to within an equave, allowing voicings that span multiple octaves. Exact duplicates are removed, but the same pitch-class in different octaves is allowed.

Parameters:
  • degrees (list of str, float, int, or Fraction) – Intervals as ratios, decimals, or numbers.

  • interval_type (str, optional) – "ratios" or "cents". Default is "ratios".

  • equave (float, Fraction, int, or str, optional) – Interval of equivalence. Default is "2/1".

  • reference_pitch (Pitch, str, or None, optional) – If provided, the voicing is instanced at this pitch.

Examples

>>> voicing = Voicing(["1/2", "1/1", "3/2", "5/2"])
>>> voicing.degrees
[Fraction(1, 2), Fraction(1, 1), Fraction(3, 2), Fraction(5, 2)]
>>> voicing = Voicing(["1/1", "1/1", "3/2"])
>>> voicing.degrees
[Fraction(1, 1), Fraction(3, 2)]
__init__(degrees=['1/1', '5/4', '3/2'], interval_type='ratios', equave='2/1', reference_pitch=None)[source]
property intervals: List[float | Fraction]

Successive intervals between adjacent voicing tones.

Type:

list

property degrees: List[Pitch | float | Fraction]

The voicing degrees. Returns Pitch objects when instanced.

Type:

list

relative()[source]

Return a rootless copy retaining only the interval structure.

Return type:

Voicing

root(pitch)[source]

Return a copy rooted at the given pitch.

Parameters:

pitch (Pitch or str) – The reference pitch.

Return type:

Voicing

classmethod from_collection(collection, equave=None)[source]

Construct a Voicing from an existing relative pitch collection.

Parameters:
  • collection (PitchCollectionBase) – A relative pitch collection to convert.

  • equave (float, Fraction, int, str, or None, optional) – Override equave. Defaults to the collection’s equave.

Return type:

Voicing

Raises:

ValueError – If the collection is absolute (not relative).

class klotho.tonos.chords.chord.ChordSequence(chords=None)[source]

Bases: object

An ordered sequence of Chord or Voicing objects.

Provides a container for chord progressions or harmonic sequences.

Parameters:

chords (list of Chord or Voicing, optional) – The chord objects in the sequence.

Examples

>>> chord1 = Chord(["1/1", "5/4", "3/2"])
>>> chord2 = Chord(["1/1", "6/5", "3/2"])
>>> sequence = ChordSequence([chord1, chord2])
>>> len(sequence)
2
__init__(chords=None)[source]
property chords: List[Chord | Voicing]

A copy of the chord objects in this sequence.

Type:

list

klotho.tonos.chords.chord.InstancedChord

alias of Chord

klotho.tonos.chords.chord.InstancedVoicing

alias of Voicing

Systems

Combination Product Sets

CPS Core

class klotho.tonos.systems.combination_product_sets.combination_product_sets.CombinationProductSet(factors, r, master_set, normalized=False)[source]

Bases: CombinationSet

A Combination Product Set (CPS) scale.

A CPS is a scale generated by taking all k-element combinations of a set S of n positive integers, computing their products, equave-reducing, and sorting. The resulting pitches form a highly symmetrical scale used extensively in just-intonation microtonality.

Named presets (hexany, dekany, etc.) are available as classmethods.

Parameters:
  • factors (tuple of int) – The generator factors.

  • r (int) – Combination rank (number of factors multiplied per product).

  • master_set (str or MasterSet) – Geometric layout template. Available presets can be found in MASTER_SETS.

  • normalized (bool, optional) – If True, normalize ratios by the largest factor. Default is False.

References

Examples

>>> cps = CombinationProductSet.hexany((1, 3, 5, 7))
>>> cps.ratios
(Fraction(1, 1), Fraction(7, 6), ...)
__init__(factors, r, master_set, normalized=False)[source]
property positions

Mapping of node IDs to their computed geometric positions.

Type:

dict

property master_set

The name of the master set layout template.

Type:

str

property master_set_instance

The resolved master set instance with factor assignments.

Type:

MasterSet

property aliases

Mapping from integer factors to symbolic aliases.

Type:

dict

property products

Sorted tuple of raw combination products (before equave reduction).

Type:

tuple

property ratios

Sorted tuple of equave-reduced ratios.

Type:

tuple

get_node_by(attr_name, value)[source]

Find the first node whose attribute matches the given value.

Parameters:
  • attr_name (str) – Node attribute name to search.

  • value – Value to match.

Returns:

The node ID, or None if not found.

Return type:

int or None

get_attrs_by(attr_name, value)[source]

Return the full attribute dict of the first node matching a given attribute.

Parameters:
  • attr_name (str) – Node attribute name to search.

  • value – Value to match.

Returns:

The node attribute dictionary, or None if not found.

Return type:

dict or None

classmethod hexany(factors=(1, 3, 5, 7), master_set='tetrad', normalized=False)[source]

Hexany – a six-note CPS from 4 factors taken 2 at a time.

Parameters:
  • factors (tuple of int, optional) – Exactly 4 generator factors. Default is (1, 3, 5, 7).

  • master_set (str or MasterSet, optional) – Geometric layout template. Default is 'tetrad'.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

References

classmethod dekany(factors=(1, 3, 5, 7, 11), r=2, master_set='arrow', normalized=False)[source]

Dekany – a 10-note CPS from 5 factors taken 2 or 3 at a time.

Parameters:
  • factors (tuple of int, optional) – Exactly 5 generator factors.

  • r (int, optional) – Combination rank (2 or 3). Default is 2.

  • master_set (str or MasterSet, optional) – Geometric layout template. Default is 'arrow'.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

References

classmethod pentadekany(factors=(1, 3, 5, 7, 11, 13), r=2, master_set='asterisk', normalized=False)[source]

Pentadekany – a 15-note CPS from 6 factors taken 2 or 4 at a time.

Parameters:
  • factors (tuple of int, optional) – Exactly 6 generator factors.

  • r (int, optional) – Combination rank (2 or 4). Default is 2.

  • master_set (str or MasterSet, optional) – Geometric layout template. Default is 'asterisk'.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

References

classmethod eikosany(factors=(1, 3, 5, 7, 9, 11), master_set='asterisk', normalized=False)[source]

Eikosany – a 20-note CPS from 6 factors taken 3 at a time.

Parameters:
  • factors (tuple of int, optional) – Exactly 6 generator factors.

  • master_set (str or MasterSet, optional) – Geometric layout template. Default is 'asterisk'.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

References

classmethod hebdomekontany(factors=(1, 3, 5, 7, 9, 11, 13, 17), master_set='ogdoad', normalized=False)[source]

Hebdomekontany – a 70-note CPS from 8 factors taken 4 at a time.

Parameters:
  • factors (tuple of int, optional) – Exactly 8 generator factors.

  • master_set (str or MasterSet, optional) – Geometric layout template. Default is 'ogdoad'.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

References

classmethod from_rules(factors, rules, master_set, normalized=False)[source]

Construct a CPS from declarative rules instead of a single rank.

Rules describe which combinations (products, powers, or ratios) to include, allowing hybrid CPS structures.

Parameters:
  • factors (tuple of int) – Generator factors.

  • rules (list of tuple) – Each rule is a tuple whose first element is the operation ('product', 'power', or 'ratio') followed by operation-specific arguments.

  • master_set (str or MasterSet) – Geometric layout template.

  • normalized (bool, optional) – Normalize ratios by the largest factor. Default is False.

Return type:

CombinationProductSet

Master Sets

class klotho.tonos.systems.combination_product_sets.master_set.MasterSet(positions, edges, name=None, factors=None)[source]

Bases: object

A geometric layout template for Combination Product Sets.

Defines node positions and edges that determine the spatial arrangement and relational structure of CPS nodes. Named constructors (tetrad, asterisk, etc.) provide common geometric templates in 2-D, 3-D, or N-D.

Parameters:
  • positions (dict) – Mapping of single-letter node labels to coordinate tuples.

  • edges (list of tuple) – Pairs of node labels defining the edge connections.

  • name (str or None, optional) – Human-readable name for this layout.

  • factors (tuple of int or None, optional) – If provided, assigns integer factors to node labels in sorted order.

__init__(positions, edges, name=None, factors=None)[source]
property dimensionality

The effective spatial dimensionality (2 or more).

Type:

int

property relationship_dict

Symbolic ratio keys mapping to angle, distance, and displacement data.

Type:

dict

property positions

Mapping of node labels to coordinate tuples.

Type:

dict

property n_factors

The number of factor nodes in this layout.

Type:

int

property name

The layout template name.

Type:

str or None

property edges

Edge pairs as (from_label, to_label).

Type:

list of tuple

property factors

The integer factors assigned to node labels.

Type:

tuple of int or None

property factor_to_alias

Mapping from integer factors to single-letter aliases.

Type:

dict or None

property alias_to_factor

Mapping from single-letter aliases to integer factors.

Type:

dict or None

property aliases

Sorted single-letter node aliases.

Type:

list of str

property ratios

Equave-reduced ratios of the assigned factors.

Type:

tuple of Fraction or None

node_data()[source]

Return a dict of per-node data including alias, factor, and ratio.

Returns:

Keyed by alias letter, values are dicts with 'alias', 'factor', and 'ratio' entries.

Return type:

dict

with_factors(factors)[source]

Return a new MasterSet with specific factors assigned.

Parameters:

factors (tuple of int) – Integer factors to assign to the node positions.

Return type:

MasterSet

classmethod tetrad()[source]
classmethod asterisk()[source]
classmethod centered_pentagon()[source]
classmethod connected_centered_pentagon()[source]
classmethod hexagon()[source]
classmethod irregular_hexagon()[source]
classmethod ogdoad()[source]
classmethod heptagon()[source]
classmethod kite()[source]
classmethod arrow()[source]
classmethod k23_bipartite()[source]
classmethod wheel5()[source]
classmethod bowtie()[source]
classmethod house()[source]
classmethod wheel4()[source]
classmethod h_shape()[source]
classmethod nested_triangles()[source]
classmethod tetrad_3d()[source]
classmethod octahedron()[source]
classmethod trigonal_bipyramid()[source]
classmethod triangular_prism()[source]
classmethod pentagonal_bipyramid()[source]
classmethod kite_pyramid()[source]
classmethod asterisk_nd()[source]
classmethod ogdoad_nd()[source]
classmethod twisted_asterisk_s2()[source]

Center + 5 spokes along a deterministic Fibonacci spiral on S^2.

Native 3-D, 6 nodes. Fits any 6-factor nkany preset (Pentadekany, Eikosany). Spokes are at unit directions determined only by the node index, so the geometry is entirely number-agnostic.

Return type:

MasterSet

classmethod antiprism_3()[source]

Trigonal antiprism: two triangles rotated 60 degrees along z.

Native 3-D, 6 nodes, no center hub. Top triangle is slightly smaller than the bottom to break translational symmetry that would otherwise trigger subset-sum collisions. Fits any 6-factor nkany preset.

Return type:

MasterSet

classmethod halton_asterisk(n=6, ambient_d=5)[source]

Center + (n-1) unit spokes on S^(ambient_d - 1) via Halton inverse-CDF.

A generic-position N-D generalization of Klotho’s asterisk family. Default (n=6, ambient_d=5) matches the node count and ambient dimension of asterisk_nd while replacing its orthogonal-axes geometry with deterministically quasi-random unit spokes.

Parameters:
  • n (int, optional) – Number of master-set nodes (1 center + n-1 spokes). Default 6.

  • ambient_d (int, optional) – Ambient dimension. Default 5.

Return type:

MasterSet

classmethod wheel_nd(n=6, ambient_d=5)[source]

Hub + ring of (n-1) outer nodes, with per-label Halton offsets in every dim >= 2.

The outer ring lives in dims 0/1 as a regular polygon; each ring node additionally receives a unique, deterministic offset in every higher dim, which makes the master set genuinely N-D while preserving hub-and-ring topology. Default parameters (n=6, ambient_d=5) match asterisk_nd’s factor count and ambient dim.

Parameters:
  • n (int, optional) – Number of master-set nodes (1 hub + n-1 ring nodes). Default 6.

  • ambient_d (int, optional) – Ambient dimension. Default 5. Must be >= 2.

Return type:

MasterSet

CPS Algorithms

klotho.tonos.systems.combination_product_sets.algorithms.match_pattern(cps, node_ids, sort_by='position', include_target=False)[source]

Find all groups of nodes forming the same geometric shape as the input nodes.

The match is purely geometric: two node sets match if they occupy congruent positions (same shape, allowing rotation and reflection). Each returned match is ordered so that match[i] occupies the same structural position as node_ids[i].

Parameters:
  • cps (CombinationProductSet) – The CPS instance to search.

  • node_ids (list of int) – Node IDs defining the reference shape.

  • sort_by (str, optional) –

    How to order results:

    • 'position' (default) – clockwise spatial sweep based on centroid angular position relative to the target.

    • 'rotation' – clockwise Procrustes rotation angle.

  • include_target (bool, optional) – If True, prepend the target itself as the first result. Default is False.

Returns:

Matching node-ID tuples, ordered to correspond positionally with node_ids.

Return type:

list of tuple of int

klotho.tonos.systems.combination_product_sets.algorithms.sub_cps(cps, k, s)[source]

Enumerate all sub-CPS structures within a CPS.

A sub-CPS is formed by fixing an anchor subset of factors and varying the remaining k factors taken s at a time.

Parameters:
  • cps (CombinationProductSet) – The parent CPS.

  • k (int) – Number of varying factors in each sub-CPS.

  • s (int) – Combination rank within the sub-CPS.

Returns:

Each dict contains 'nodes', 'anchor', 'varying', and 'combos' keys.

Return type:

list of dict

klotho.tonos.systems.combination_product_sets.algorithms.classify(cps, node_ids)[source]

Classify a subset of CPS nodes as harmonic, subharmonic, or mixed.

Harmonic subsets share common anchor factors; subharmonic subsets exclude factors entirely; mixed subsets do neither.

Parameters:
Returns:

Classification result with keys 'type', 'nodes', 'shared', 'excluded', and 'factors_present'.

Return type:

dict

klotho.tonos.systems.combination_product_sets.algorithms.faces(cps, size)[source]

Find all fully-connected cliques of a given size in the CPS graph.

A face is a subset of nodes where every pair is connected by an edge (a complete subgraph).

Parameters:
Returns:

Each tuple contains the node IDs forming a complete subgraph.

Return type:

list of tuple of int

Harmonic Trees

Harmonic Tree Core

class klotho.tonos.systems.harmonic_trees.harmonic_tree.HarmonicTree(root=1, children=(1,), equave=None, span=1)[source]

Bases: Tree

__init__(root=1, children=(1,), equave=None, span=1)[source]
property harmonics

Raw harmonic values at each leaf node (product along path from root).

Type:

tuple

property ratios

Equave-reduced ratios at each leaf node (or raw harmonics if no equave).

Type:

tuple

property equave

The interval of equivalence, or None if reduction is disabled.

Type:

Fraction or None

property span

Number of equaves used for the reduction window.

Type:

int

Spectrum

class klotho.tonos.systems.harmonic_trees.spectrum.Spectrum(fundamental, partials)[source]

Bases: object

A harmonic spectrum built from a fundamental frequency and partial numbers.

Manages a collection of pitches derived from a fundamental and a list of partial numbers (harmonic or non-harmonic). Provides operations for reinterpreting, retargeting, and modulating the spectrum.

Parameters:
  • fundamental (int, float, or Pitch) – The fundamental frequency (Hz) or a Pitch object.

  • partials (list of int, float, or Fraction) – Partial numbers defining the spectrum.

Examples

>>> spectrum = Spectrum(Pitch('A', 4), [1, 2, 3, 4])
>>> spectrum = Spectrum.from_target(Pitch('A', 4, partial=3), [1, 2, 3, 4])
__init__(fundamental, partials)[source]
property fundamental

The fundamental pitch of the spectrum.

Type:

Pitch

property partials

The partial numbers present in the spectrum.

Type:

tuple

property data

Tabular data with partial, frequency, pitch, and offset columns.

Type:

pandas.DataFrame

property ht

The underlying harmonic tree structure.

Type:

HarmonicTree

__getitem__(key)[source]

Get a Pitch by its partial number.

Parameters:

key (int or float) – The partial number to retrieve.

Returns:

The Pitch corresponding to the partial number.

Return type:

Pitch

Raises:

KeyError – If the partial number does not exist in the spectrum.

classmethod from_target(target, partials)[source]

Create a Spectrum where target is a known partial rather than the fundamental.

The fundamental is back-calculated from the target pitch and its partial number.

Parameters:
  • target (Pitch) – A Pitch whose partial attribute identifies which partial it represents.

  • partials (list of int, float, or Fraction) – Partial numbers to include.

Return type:

Spectrum

Raises:

ValueError – If the target’s partial number is not in partials.

pivot(source_partial, target_partial)[source]

Reinterpret a partial as a different partial number, adjusting the fundamental.

Parameters:
  • source_partial (int or float) – The partial number to reinterpret.

  • target_partial (int or float) – The new partial number to assign.

Returns:

A new Spectrum with the adjusted fundamental.

Return type:

Spectrum

Raises:

ValueError – If either partial is not in the spectrum.

retarget(partial, target)[source]

Adjust the spectrum so that the given partial matches target.

Parameters:
  • partial (int or float) – The partial number to adjust.

  • target (Pitch) – The target pitch to match.

Returns:

A new Spectrum with the adjusted fundamental.

Return type:

Spectrum

Raises:

ValueError – If the partial is not in the spectrum.

modulate(target, source_partial, target_partial)[source]

Adjust this spectrum so that source_partial aligns with target_partial in another spectrum.

Parameters:
  • target (Spectrum) – The target spectrum to align with.

  • source_partial (int or float) – Partial number from this spectrum to adjust.

  • target_partial (int or float) – Partial number from the target spectrum to match.

Returns:

A new Spectrum with the adjusted fundamental.

Return type:

Spectrum

Raises:

ValueError – If either partial is not found in its respective spectrum.

Harmonic Tree Algorithms

klotho.tonos.systems.harmonic_trees.algorithms.measure_partials(partials, f=1)[source]

Recursively compute absolute partial values from a nested partial specification.

Supports both flat sequences of partials and nested (factor, sub_partials) tuples for hierarchical harmonic structures.

Parameters:
  • partials (tuple) – Partial numbers. An element may be an int (or negative int for undertones) or a (factor, sub_partials) tuple for recursion.

  • f (int or float, optional) – Cumulative multiplication factor from parent levels. Default is 1.

Returns:

Flat tuple of computed partial values.

Return type:

tuple

Tone Lattices

Tone Lattice Core

exception klotho.tonos.systems.tone_lattices.tone_lattices.ToneLatticeLookupWarning[source]

Bases: RuntimeWarning

Warning emitted when inverse ratio lookup is ambiguous or unresolved in a ToneLattice.

class klotho.tonos.systems.tone_lattices.tone_lattices.ToneLattice(dimensionality=2, resolution=10, bipolar=True, equave_reduce=True, equave=2)[source]

Bases: Lattice

Lattice of ratios represented by integer coordinates in generator space.

Coordinates are exponent vectors over an ordered generator list: ratio = g1**x1 * g2**x2 * ....

__init__(dimensionality=2, resolution=10, bipolar=True, equave_reduce=True, equave=2)[source]
classmethod from_generators(generators, resolution=10, bipolar=True, equave_reduce=True, equave=2)[source]

Build a ToneLattice from an explicit generator basis.

Parameters:
  • generators (Iterable[int | Fraction | str]) – Ordered generator ratios defining the coordinate axes.

  • resolution (int or list[int], optional) – Per-axis coordinate bounds passed to the base lattice.

  • bipolar (bool, optional) – Coordinate sign mode and equave reduction window selector.

  • equave_reduce (bool, optional) – Whether to equave-reduce represented ratios. If True and an equave generator is present, that generator axis is removed.

  • equave (int | Fraction | str, optional) – Equivalence interval used for reduction.

Return type:

ToneLattice

__getitem__(coord)[source]

Get node data for a coordinate, ensuring ratio is included.

get_ratio(coord)[source]

Return the ratio represented by a coordinate.

The value is computed in generator space and, when equave_reduce is enabled, reduced into the active equave window determined by bipolar.

Return type:

Fraction

get_coordinates_for_ratio(ratio, lookup='first', warn=True, warn_once=True)[source]

Resolve coordinate(s) for a target ratio under the current lattice state.

Parameters:
  • ratio (int | Fraction | str) – Target ratio.

  • lookup ({"first", "unique", "all"}, optional) – Resolution mode: - "first": return one deterministic coordinate match. - "unique": return coordinate only when exactly one match exists. - "all": return all matches in current lattice bounds.

  • warn (bool, optional) – Emit ToneLatticeLookupWarning when lookup fails or is ambiguous.

  • warn_once (bool, optional) – When True, suppress repeated identical warning messages per instance.

Returns:

Coordinate result according to lookup mode, or None when unresolved.

Return type:

tuple[int, …] | list[tuple[int, …]] | None

property prime_basis: List[int]

Sorted prime support inferred from active generators.

property generators: List[Fraction]

Active generator basis used by coordinate axes.

property coord_label: str

Monzo for pure prime bases, else Coordinate.

Type:

Plot label for coordinates

property equave_reduce: bool

Whether this lattice applies equave reduction to represented ratios.

__str__()[source]

String representation of the tone lattice.

Return type:

str

Basis

klotho.tonos.systems.tone_lattices.basis.find_generator_basis(primes, *, exp_bound=3, max_int=256, candidate_cap=60, include_octave=True, octave_reduce=True, ratio_lo=1, ratio_hi=2, mode='auto', random_samples=50000, seed=0, top_k=20, size_weight=1.0, size_curve=1.0, monzo_weight=0.15, monzo_curve=1.0, superparticular_weight=0.0, superparticular_severity=1.0, superparticular_curve=1.0, conditioning_max_weight=0.2, conditioning_max_curve=1.0, conditioning_sum_weight=0.01, conditioning_sum_curve=1.0, target_cents=None, target_weight=0.0, target_scale_cents=50.0, target_curve=1.0, target_fold=True, coverage=True)[source]

Find optimal generator bases for a prime-limit JI/EJI lattice.

Searches for unimodular generator sets that span the same group as the prime basis, ranked by a configurable scoring function that balances simplicity, conditioning, superparticular preference, and target intervals.

Parameters:
  • primes (List[int]) – Ordered list of prime numbers defining the prime-limit group. Example: [2, 3, 5] for 5-limit, [2, 3, 5, 7] for 7-limit.

  • Generation (Candidate)

  • --------------------

  • exp_bound (int, default 3) – Maximum absolute exponent per prime when generating candidates.

  • max_int (int, default 256) – Maximum numerator/denominator allowed in candidate ratios.

  • candidate_cap (int, default 60) – Maximum number of candidates to keep (after sorting by simplicity).

  • include_octave (bool, default True) – Force 2/1 as the first generator (recommended for pitch-class lattices).

  • octave_reduce (bool, default True) – Normalize candidates into [ratio_lo, ratio_hi) by adjusting powers of 2.

  • ratio_lo (Fraction-like, default 1) – Lower bound for octave reduction range.

  • ratio_hi (Fraction-like, default 2) – Upper bound for octave reduction range.

  • Parameters (Search)

  • -----------------

  • mode (str, default "auto") – Search strategy: “exhaustive”, “random”, or “auto”. “auto” chooses exhaustive for small search spaces, random otherwise.

  • random_samples (int, default 50000) – Number of random samples when mode=”random”.

  • seed (int, default 0) – Random seed for reproducibility.

  • top_k (int, default 20) – Number of top-scoring bases to return.

  • Scoring (Conditioning)

  • ------------------

  • size_weight (float, default 1.0) – Weight for penalizing large numerator/denominator.

  • size_curve (float, default 1.0) – Nonlinearity for size penalty (>1 harsher on large ratios).

  • monzo_weight (float, default 0.15) – Weight for penalizing large prime exponents.

  • monzo_curve (float, default 1.0) – Nonlinearity for monzo penalty.

  • Preference (Superparticular)

  • --------------------------

  • superparticular_weight (float, default 0.0) – Bonus weight for superparticular generators (negative score contribution).

  • superparticular_severity (float, default 1.0) – How strongly to prefer small-n superparticulars over large-n ones.

  • superparticular_curve (float, default 1.0) – Nonlinearity for superparticular bonus.

  • Scoring

  • --------------------

  • conditioning_max_weight (float, default 0.20) – Weight for maximum absolute entry in A_inv.

  • conditioning_max_curve (float, default 1.0) – Nonlinearity for max conditioning penalty.

  • conditioning_sum_weight (float, default 0.01) – Weight for sum of absolute entries in A_inv.

  • conditioning_sum_curve (float, default 1.0) – Nonlinearity for sum conditioning penalty.

  • Matching (Target Interval)

  • ------------------------

  • target_cents (List[float], optional) – List of desired interval sizes in cents to bias toward.

  • target_weight (float, default 0.0) – Weight for target matching penalty.

  • target_scale_cents (float, default 50.0) – Scale factor for cents distance (smaller = harsher penalty).

  • target_curve (float, default 1.0) – Nonlinearity for target penalty.

  • target_fold (bool, default True) – If True, fold cents to [0, 600] (interval class equivalence).

  • coverage (bool, default True) – If True, penalize for each target not covered by a generator. If False, penalize for each generator not near a target.

Returns:

DataFrame with columns: - generators: List of generator ratios (Fractions) - generator_cents: List of generator sizes in cents - score: Final composite score (lower is better) - simplicity_sum: Sum of generator simplicity terms - conditioning_max: Max absolute entry in A_inv - conditioning_sum: Sum of absolute entries in A_inv - superparticular_term: Superparticular bonus (negative) - target_term: Target cents penalty - conditioning_term: Conditioning penalty - det: Determinant (+/-1 for valid bases) - A: Basis matrix - A_inv: Inverse basis matrix

Sorted by score (ascending). Use standard DataFrame methods to sort/filter by other columns.

Return type:

pd.DataFrame

Examples

Basic 5-limit search:

>>> results = find_generator_basis([2, 3, 5])
>>> results[['generators', 'score']].head()

Targeting thirds with superparticular preference:

>>> results = find_generator_basis(
...     [2, 3, 5],
...     target_cents=[315.64, 386.31],
...     target_weight=1.5,
...     superparticular_weight=2.0
... )

7-limit with random search:

>>> results = find_generator_basis(
...     [2, 3, 5, 7],
...     mode="random",
...     random_samples=60000,
...     seed=42,
...     top_k=10
... )

Sort by conditioning instead of score:

>>> results.sort_values('conditioning_max')

Utilities

Frequency Conversion

class klotho.tonos.utils.frequency_conversion.PITCH_CLASSES(value)[source]

Bases: Enum

Enumeration of pitch classes for 12-TET with both sharp and flat naming.

class N_TET_12(value)[source]

Bases: Enum

C = 0
Cs = 1
Db = 1
D = 2
Ds = 3
Eb = 3
E = 4
Es = 5
Fb = 4
F = 5
Fs = 6
Gb = 6
G = 7
Gs = 8
Ab = 8
A = 9
As = 10
Bb = 10
B = 11
Bs = 0
class names[source]

Bases: object

as_sharps = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
as_flats = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']
klotho.tonos.utils.frequency_conversion.freq_to_midicents(frequency)[source]

Convert a frequency in Hertz to MIDI cents notation.

MIDI cents combine MIDI note numbers with cent offsets. A value of 6900 corresponds to A4 (440 Hz). Each increment of 100 is one 12-TET semitone; non-multiples of 100 indicate microtonal pitches.

Parameters:

frequency (float) – The frequency in Hertz.

Returns:

The MIDI cent value.

Return type:

float

Examples

>>> freq_to_midicents(440.0)
6900.0
klotho.tonos.utils.frequency_conversion.midicents_to_freq(midicents)[source]

Convert MIDI cents back to a frequency in Hertz.

Parameters:

midicents (float) – The MIDI cent value (e.g., 6900 for A4).

Returns:

The corresponding frequency in Hertz.

Return type:

float

Examples

>>> midicents_to_freq(6900)
440.0
klotho.tonos.utils.frequency_conversion.midicents_to_pitchclass(midicents)[source]

Convert MIDI cents to a pitch class with octave and cents offset.

Parameters:

midicents (float) – The MIDI cent value.

Returns:

A named tuple with fields pitchclass, octave, and cents_offset.

Return type:

namedtuple

klotho.tonos.utils.frequency_conversion.freq_to_pitchclass(freq, cent_round=4)[source]

Convert a frequency in Hertz to a pitch class with octave and cents offset.

Parameters:
  • freq (float) – The frequency in Hertz.

  • cent_round (int, optional) – Decimal places for rounding the cents offset. Default is 4.

Returns:

A named tuple with fields pitchclass, octave, and cents_offset.

Return type:

namedtuple

klotho.tonos.utils.frequency_conversion.pitchclass_to_freq(pitchclass, octave=4, cent_offset=0.0, hz_round=4, A4_Hz=440.0, A4_MIDI=69)[source]

Convert a pitch class name to a frequency in Hertz.

Parameters:
  • pitchclass (str) – Pitch class name (e.g., "C", "F#", "Bb").

  • octave (int, optional) – Octave number. Default is 4.

  • cent_offset (float, optional) – Microtonal offset in cents. Default is 0.0.

  • hz_round (int, optional) – Decimal places for rounding the result. Default is 4.

  • A4_Hz (float, optional) – Reference frequency for A4. Default is 440.0.

  • A4_MIDI (int, optional) – MIDI note number for A4. Default is 69.

Returns:

The frequency in Hertz.

Return type:

float

Harmonics

klotho.tonos.utils.harmonics.partial_to_fundamental(pitchclass, octave=4, partial=1, cent_offset=0.0)[source]

Calculate the fundamental from a pitch and its partial number.

Given a pitch that represents a specific partial of an unknown fundamental, this function back-calculates the fundamental frequency and returns its pitch-class information.

Parameters:
  • pitchclass (str) – Pitch class name (e.g., "A", "C#").

  • octave (int, optional) – Octave number. Default is 4.

  • partial (int, optional) – Partial number (non-zero). Negative values indicate undertones. Default is 1.

  • cent_offset (float, optional) – Microtonal offset in cents. Default is 0.0.

Returns:

A named tuple with fields pitchclass, octave, and cents_offset for the fundamental.

Return type:

namedtuple

Raises:

ValueError – If partial is zero.

klotho.tonos.utils.harmonics.first_equave(harmonic, equave=2, max_equave=None)[source]

Return the first equave register in which a harmonic number appears.

For example, harmonics 2 and 3 first appear in equave 1 (range 2–4), harmonic 5 first appears in equave 2 (range 4–8), etc.

Parameters:
  • harmonic (int, float, or Fraction) – The harmonic number.

  • equave (int, float, Fraction, or str, optional) – Interval of equivalence. Default is 2 (octave).

  • max_equave (int, float, Fraction, str, or None, optional) – Maximum equave register to search. None means unbounded.

Returns:

The equave register number, or None if not found within max_equave.

Return type:

int or None

Interval Normalization

klotho.tonos.utils.interval_normalization.equave_reduce(interval, equave=2, n_equaves=1)[source]

Reduce an interval into the range [1, equave^n_equaves).

Repeatedly multiplies or divides by equave until the interval falls within the target range.

Parameters:
  • interval (int, float, Fraction, or str) – The interval to reduce.

  • equave (Fraction, int, str, or float, optional) – Interval of equivalence. Default is 2 (octave).

  • n_equaves (int, optional) – Number of equaves for the reduction window. Default is 1.

Returns:

The equave-reduced interval.

Return type:

Fraction

klotho.tonos.utils.interval_normalization.reduce_interval(interval, equave=2, n_equaves=1)[source]

Fold an interval into the bipolar range [1/equave^n, equave^n).

Unlike equave_reduce, the lower bound extends below unison, allowing sub-fundamental intervals to be represented.

Parameters:
  • interval (Fraction, int, float, or str) – The interval to fold.

  • equave (Fraction, int, float, or str, optional) – Interval of equivalence. Default is 2.

  • n_equaves (int, optional) – Number of equaves for the range. Default is 1.

Returns:

The folded interval.

Return type:

Fraction

klotho.tonos.utils.interval_normalization.reduce_interval_relative(target, source, equave=2)[source]

Fold target to the equave transposition closest to source.

Searches upward and downward by equave until the minimum absolute distance from source is found.

Parameters:
  • target (Fraction, int, float, or str) – The interval to fold.

  • source (Fraction, int, float, or str) – The reference interval.

  • equave (Fraction, int, float, or str, optional) – Interval of equivalence. Default is 2.

Returns:

The transposition of target that minimizes |source - target|.

Return type:

Fraction

klotho.tonos.utils.interval_normalization.reduce_sequence_relative(sequence, equave=2)[source]

Fold a sequence of intervals to minimise octave jumps between neighbours.

The first and last intervals are kept as anchors. Interior intervals are folded forward then backward to minimise adjacent displacement.

Parameters:
  • sequence (list of Fraction, int, float, or str) – Intervals to fold.

  • equave (Fraction, int, float, or str, optional) – Interval of equivalence. Default is 2.

Returns:

Folded intervals preserving the original start and end values.

Return type:

list of Fraction

klotho.tonos.utils.interval_normalization.fold_interval(interval, lower_thresh, upper_thresh)[source]

Reflect an interval back inside explicit threshold boundaries.

If the interval exceeds the upper threshold, it is reflected downward by the overshoot distance; if below the lower threshold, it is reflected upward.

Parameters:
  • interval (Fraction, int, float, or str) – The interval to fold.

  • lower_thresh (Fraction, int, float, or str) – Lower boundary.

  • upper_thresh (Fraction, int, float, or str) – Upper boundary.

Returns:

The folded interval.

Return type:

Fraction

klotho.tonos.utils.interval_normalization.reduce_freq(freq, lower=27.5, upper=4186, equave=2)[source]

Fold a frequency into a bounded range by equave transposition.

Parameters:
  • freq (float) – The frequency to fold.

  • lower (float, optional) – Lower bound in Hertz. Default is 27.5 (A0).

  • upper (float, optional) – Upper bound in Hertz. Default is 4186 (C8).

  • equave (int, float, Fraction, or str, optional) – Interval of equivalence. Default is 2.

Returns:

The frequency folded into [lower, upper].

Return type:

float

Intervals

klotho.tonos.utils.intervals.ratio_to_cents(ratio, round_to=4)[source]

Convert a musical interval ratio to cents.

Cents are a logarithmic unit where 1200 cents equals one octave (2/1).

Parameters:
  • ratio (int, float, Fraction, or str) – The interval ratio (e.g., '3/2', 1.5).

  • round_to (int, optional) – Decimal places to round the result. Default is 4.

Returns:

The interval size in cents.

Return type:

float

Examples

>>> ratio_to_cents('3/2')
701.955
klotho.tonos.utils.intervals.cents_to_ratio(cents)[source]

Convert cents to a frequency ratio.

Parameters:

cents (float) – The interval in cents.

Returns:

The corresponding frequency ratio.

Return type:

float

Examples

>>> cents_to_ratio(1200)
2.0
klotho.tonos.utils.intervals.cents_to_setclass(cent_value=0.0, n_tet=12, round_to=2)[source]

Convert a cent value to a pitch-class number in an equal-tempered system.

Parameters:
  • cent_value (float, optional) – Interval in cents. Default is 0.0.

  • n_tet (int, optional) – Number of equal divisions per octave. Default is 12.

  • round_to (int, optional) – Decimal places to round to. Default is 2.

Returns:

The pitch-class number.

Return type:

float

klotho.tonos.utils.intervals.ratio_to_setclass(ratio, n_tet=12, round_to=2)[source]

Convert a musical interval ratio to a pitch-class number.

Parameters:
  • ratio (str or float) – The interval ratio (e.g., '3/2').

  • n_tet (int, optional) – Number of equal divisions per octave. Default is 12.

  • round_to (int, optional) – Decimal places to round to. Default is 2.

Returns:

The pitch-class number.

Return type:

float

klotho.tonos.utils.intervals.fold_cents_symmetric(cents)[source]

Fold a cents value into the range [0, 600].

This implements interval class equivalence, treating intervals and their inversions as equivalent. A minor third (~316 cents) and a major sixth (~884 cents) both fold to ~316 cents.

The folding works by: 1. Taking the absolute value 2. Reducing modulo 1200 (one octave) 3. If > 600, reflecting: 1200 - value

Parameters:

cents (float) – Cents value to fold.

Returns:

Folded cents value in range [0, 600].

Return type:

float

Examples

>>> fold_cents_symmetric(316.0)  # minor third
316.0
>>> fold_cents_symmetric(884.0)  # major sixth (inversion of m3)
316.0
>>> fold_cents_symmetric(702.0)  # fifth
498.0
>>> fold_cents_symmetric(-316.0)  # negative minor third
316.0
klotho.tonos.utils.intervals.split_partial(interval, n=2)[source]

Find the smallest harmonic subdivision of an interval into n equal steps.

Returns a sequence of n + 1 integers [a₀, a₁, …, aₙ] where each adjacent pair forms the same ratio and aₙ / a₀ equals the target interval.

Parameters:
  • interval (int, float, Fraction, or str) – The target interval ratio to subdivide.

  • n (int, optional) – Number of equal subdivisions. Default is 2.

Returns:

A named tuple with fields:

  • harmonics – list of n + 1 integers forming the subdivision.

  • k – the smallest starting integer that yields a valid result.

Return type:

namedtuple

Examples

>>> split_partial('3/2', 2)
result(harmonics=[4, 5, 6], k=4)
klotho.tonos.utils.intervals.harmonic_mean(a, b)[source]

Calculate the harmonic mean of two values: 2 / (1/a + 1/b).

In music, the harmonic mean of two intervals produces the interval that divides the span harmonically (unequal division weighted toward the smaller value).

Parameters:
Returns:

The harmonic mean.

Return type:

Fraction

klotho.tonos.utils.intervals.arithmetic_mean(a, b)[source]

Calculate the arithmetic mean of two values: (a + b) / 2.

In music, the arithmetic mean of two intervals produces the interval that divides the span arithmetically (equal division by frequency difference).

Parameters:
Returns:

The arithmetic mean.

Return type:

Fraction

klotho.tonos.utils.intervals.harmonic_distance(ratio)[source]

Compute the Tenney height (harmonic distance) of a ratio.

For a ratio p/q in lowest terms the Tenney height is defined as log2(p * q). Simpler ratios (small numerator and denominator) yield lower values; more complex ratios yield higher values.

Parameters:

ratio (int, float, Fraction, or str) – The ratio to measure. Strings like '3/2' are accepted.

Returns:

The Tenney height (base-2 logarithm of numerator * denominator).

Return type:

float

Examples

>>> harmonic_distance('3/2')
2.584962500721156
>>> harmonic_distance('5/4')
4.321928094887363
>>> harmonic_distance(Fraction(9, 8))
6.169925001442312
klotho.tonos.utils.intervals.logarithmic_distance(a, b, equave=2)[source]

Calculate the logarithmic distance between two musical intervals.

Parameters:
  • a (int, float, Fraction, or str) – First interval.

  • b (int, float, Fraction, or str) – Second interval.

  • equave (int, float, Fraction, or str, optional) – Base for logarithmic scaling. Default is 2 (octave).

Returns:

The absolute logarithmic distance.

Return type:

float

klotho.tonos.utils.intervals.interval_cost(a, b, diff_coeff=1.0, prime_coeff=1.0, equave=2)[source]

Compute a weighted cost of moving between two intervals.

Combines logarithmic distance with prime-factorization distance.

Parameters:
  • a (int, float, Fraction, or str) – First interval.

  • b (int, float, Fraction, or str) – Second interval.

  • diff_coeff (float, optional) – Weight for logarithmic distance. Default is 1.0.

  • prime_coeff (float, optional) – Weight for prime-exponent difference. Default is 1.0.

  • equave (int, float, Fraction, or str, optional) – Base for logarithmic scaling. Default is 2.

Returns:

The weighted cost.

Return type:

float

klotho.tonos.utils.intervals.n_tet(divisions=12, equave=2, nth_division=1, symbolic=False)[source]

Calculate the frequency ratio of the nth step in an equal temperament.

Parameters:
  • divisions (int, optional) – Number of equal divisions of the equave. Default is 12.

  • equave (int, float, Fraction, or str, optional) – The interval to divide. Default is 2 (octave).

  • nth_division (int, optional) – Which step to compute. Default is 1.

  • symbolic (bool, optional) – If True, return a sympy expression instead of a float. Default is False.

Returns:

The frequency ratio.

Return type:

float or sympy.Rational

klotho.tonos.utils.intervals.ratios_n_tet(divisions=12, equave=2, symbolic=False)[source]

Return all step ratios for an equal temperament.

Parameters:
  • divisions (int, optional) – Number of equal divisions. Default is 12.

  • equave (int, float, Fraction, or str, optional) – The interval to divide. Default is 2 (octave).

  • symbolic (bool, optional) – If True, return sympy expressions. Default is False.

Returns:

Frequency ratios for steps 0 through divisions - 1.

Return type:

list of float or sympy.Rational

References