Periodic package API documentation

xenharmlib.periodic.cutouts(scale: ScaleT, mask_expr: int | Tuple[int, ...]) Generator[ScaleT]

Returns a generator yielding partial scales obtained by sliding a mask over the periodical extension of the scale until periodic equivalence is detected.

The function can be used to generate all triads or seven chord scales from a key scale. For example:

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>>
>>> for chord_scale in periodic.cutouts(c_maj, (0, 2, 4)):
...    print(chord_scale)
UpDownNoteScale([C0, E0, G0], 12-EDO)
UpDownNoteScale([D0, F0, A0], 12-EDO)
UpDownNoteScale([E0, G0, B0], 12-EDO)
UpDownNoteScale([F0, A0, C1], 12-EDO)
UpDownNoteScale([G0, B0, D1], 12-EDO)
UpDownNoteScale([A0, C1, E1], 12-EDO)
UpDownNoteScale([B0, D1, F1], 12-EDO)
Parameters:
  • scale – The scale from which the partials are taken

  • mask_expr – An index mask expression defining the template that the generator slides over the scale.

xenharmlib.periodic.find_iseq(scale, interval_seq) List[Tuple[int, ...]]

Searches an interval sequence in the periodic extension of the given scale and returns a list of periodic index masks indicating the partial scales which fit the sequence.

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_major_scale = n_edo12.natural_scale()
>>> c_major_triad = c_major_scale.partial((0, 2, 4))
>>> major_triad = c_major_triad.to_interval_seq()
>>>
>>> periodic.find_iseq(c_major_scale, major_triad)
[(0, 2, 4), (3, 5, 7), (4, 6, 8)]
Parameters:
  • scale – A period normalized scale

  • interval_seq – An interval sequence

xenharmlib.periodic.index(scale: PeriodicScale[FreqReprT], element: FreqReprT) int

Returns the index where an element is found in the periodic extension of a period normalized scale

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.index(c_maj, n_edo12.note('D', 1))
8
Parameters:
  • scale – A period normalized scale

  • element – The element to be found

Raises:
  • ValueError – If given scale is not period normalized

  • ValueError – If element was not found in periodic extension

xenharmlib.periodic.index_mask(parent: ScaleT, partial: ScaleT) Tuple[int, ...]

Searches for a partial scale in a scale and returns the periodic index mask of where the partial scale can be found.

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> Bdim = n_edo12.pc_scale(['B', 'D', 'F'])
>>> periodic.index_mask(c_maj, Bdim)
(6, 8, 10)
Parameters:
  • parent – The parent scale to search in

  • partial – The partial scale that should be found

Raises:
  • IncompatibleOriginContexts – If parent scale and partial scale are not from the same origin context

  • ValueError – If parent scale is not period normalized

  • ValueError – If partial scale was not found in periodic extension of the reference scale

xenharmlib.periodic.is_in(scale: PeriodicScale[FreqReprT], element: FreqReprT) bool

Returns bool if element exists in periodic extension of a period normalized scale

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.is_in(c_maj, n_edo12.note('D', 1))
True
Parameters:
  • scale – A period normalized scale

  • element – The element to be found

Raises:
  • ValueError – If given scale is not period normalized

  • IncompatibleOriginContexts – If element and scale have different origin contexts

xenharmlib.periodic.mod_connectors(scale_a, scale_b, cutout_pattern)

Returns partial scales of a specific structure (such as I-III-V) that are shared between two scales. These partial scales can be interpreted as chords that connect two different keys (“modulation connectors”). If you e.g. want to pivot from C major to G minor using standard triads you can get the key-connecting chords like this:

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib.periodic import mod_connectors
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> g_min = n_edo12.pc_scale(['G', 'A', 'Bb', 'C', 'D', 'Eb', 'F'])
>>>
>>> for connector in mod_connectors(c_maj, g_min, (0, 2, 4)):
...     print(connector)
UpDownNoteScale([D0, F0, A0], 12-EDO)
UpDownNoteScale([F0, A0, C1], 12-EDO)

Since in theory every shared partial scale has infinite equivalents on the periodic extension the scales are normalized to the first occurence in the first scale

Parameters:
  • scale_a – The first scale

  • scale_b – The second scale

  • cutout_pattern – A mask expression used to iteratively cut out partial scales from the two scales.

xenharmlib.periodic.pairs(scale: PeriodicScale[FreqReprT], distance: int = 1) Generator[Tuple[FreqReprT, FreqReprT]]

Returns a generator yielding tuples of neighboring elements of the periodic extension of a scale (either direct neighbors or neighbors with a bigger fixed distance)

Parameters:
  • scale – The origin scale

  • distance – The distance of the two elements (optional, defaults to 1 meaning “direct neighbors”)

xenharmlib.periodic.partial(scale: ScaleT, mask_expr: int | Tuple[int | EllipsisType, ...]) ScaleT

Returns a new scale consisting of a selection of indices of the periodic extension of the given scale. The selection is defined by an index mask expression.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a scale including the second, third and sixth element of the origin scale

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

Indices in the mask expression can be greater or smaller than the available indices in the origin scale. In this case the elements are taken from the periodic extension, e.g.

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.partial(c_maj, (-1, 1, 3))
UpDownNoteScale([B-1, D0, F0], 12-EDO)
>>> periodic.partial(c_maj, (5, ..., 12))
UpDownNoteScale([A0, B0, C1, D1, E1, F1, G1, A1], 12-EDO)

If only one element should be selected a simple integer can be used

Parameters:
  • scale – A period normalized scale

  • mask_expr – An index mask expression which defines the selection of indices from the periodic extension of the origin scale.

Raises:

ValueError – If given scale is not period normalized

xenharmlib.periodic.scalar_transpose(ref_scale: ScaleT, transposable: ScaleT | FreqReprT, steps: int) ScaleT | FreqReprT

Scalar transposition moves a note, pitch or scale along the steps of a reference scale. This is in contrast to normal transposition which moves a note along the steps of the complete scale (e.g. the chromatic scale in 12-EDO):

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.scalar_transpose(c_maj, n_edo12.note('D', 1), 3)
UpDownNote(G, 1, 12-EDO)

When scalar transposition is applied to collections of notes or pitches interval content can change, for example if a C major triad is transposed 1 step in reference to the C major scale the result will be D minor(!):

>>> triad = n_edo12.pc_scale(['C', 'E', 'G'])
>>> periodic.scalar_transpose(c_maj, triad, 1)
UpDownNoteScale([D0, F0, A0], 12-EDO)
Parameters:
  • ref_scale – A period normalized reference scale

  • transposable – The object to be transposed

  • steps – The number of scale steps the object should be transposed

Raises:
  • IncompatibleOriginContexts – If reference scale and tranposable are not from the same origin context

  • ValueError – If reference scale is not period normalized

  • ValueError – If transposable object was not found in periodic extension of the reference scale

xenharmlib.periodic.scale_element(scale: PeriodicScale[FreqReprT], index: int) FreqReprT

Gets an element at a given index from the periodic extension of a period normalized scale.

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.scale_element(c_maj, 8)
UpDownNote(D, 1, 12-EDO)
Parameters:
  • scale – A period normalized scale

  • index – An index of the periodic extension of the scale

Raises:

ValueError – If given scale is not period normalized

xenharmlib.periodic.spec_interval(scale: PeriodicScale, source_index: int, target_index: int) Interval

Returns the specific interval for a generic interval of the periodic extension of the scale.

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib import periodic
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> c_maj = n_edo12.pc_scale(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
>>> periodic.spec_interval(c_maj, 6, 7)
UpDownNoteInterval(m, 2, 12-EDO)
Parameters:
  • scale – A period normalized scale

  • source_index – Periodic source index for the interval

  • target_index – Periodic target index for the interval