ToneCollection

ToneCollection(
    tones: Iterable[Tone] = (),
    root: Tone | None = None,
    name: str | None = None,
)

An ordered collection of tones, with an optional root and optional name.

Tone order is preserved and is musically significant: for example, it is what distinguishes a chord with an added 2nd from one with an added 9th, even though both consist of the same pitch classes.

Note that name can be a formattable string including {root}, which allows chord names to update automatically in the case of transposition. {root} renders as the root’s display form (see Tone.__format__), so {root:ascii} and the like also work.

Equality and hashing are based on tones and root only (not name), so two ToneCollections built from the same tones and root compare equal even if they were given different names – but they remain distinct objects (is is unaffected).

A collection is a sequence of its tones (length, indexing, membership, iteration) with a root and a name:

>>> from openmusickit.systems.wsmn.tonal.symbols import C, E, G
>>> triad = ToneCollection([C, E, G], root=C, name="{root} major")
>>> len(triad), triad[1], E in triad, triad.name
(3, TonalVector((2, 4)), True, 'C major')
>>> triad == ToneCollection([C, E, G], root=C, name="anything")
True

Attributes

Name Description
tones
root
name_template
name The name template formatted with root.

Methods

Name Description
__init__
__iter__
__len__
__getitem__
__contains__
__repr__
combinations Returns a list of all ToneCollection subsets of k members, in the collection’s order.
all_combinations Returns a list of all ToneCollection subsets of length 2 through len(self)-1.
transform Returns a new ToneCollection made by applying operation to every

__init__

__init__(
    tones: Iterable[Tone] = (),
    root: Tone | None = None,
    name: str | None = None,
)

__iter__

__iter__()

__len__

__len__()

__getitem__

__getitem__(index)

__contains__

__contains__(tone)

__repr__

__repr__()

combinations

combinations(k: int)

Returns a list of all ToneCollection subsets of k members, in the collection’s order.

>>> from openmusickit.systems.wsmn.tonal.symbols import C, E, G
>>> [[format(t) for t in dyad] for dyad in ToneCollection([C, E, G]).combinations(2)]
[['C', 'E'], ['C', 'G'], ['E', 'G']]

all_combinations

all_combinations()

Returns a list of all ToneCollection subsets of length 2 through len(self)-1.

>>> from openmusickit.systems.wsmn.tonal.symbols import C, E, G, B
>>> len(ToneCollection([C, E, G, B]).all_combinations())  # 6 dyads and 4 triads
10

transform

transform(
    operation: Callable[..., Tone],
    *args,
    new_name: str | None = None,
    **kwargs,
)

Returns a new ToneCollection made by applying operation to every tone of this collection (and to root, if set).

operation is called as operation(tone, *args, **kwargs) for each tone. It is typically a method of the relevant Tone subclass (such as TonalVector.transpose), but any callable that accepts a Tone as its first argument and returns a Tone will do. If the operation returns something that is not a Tone, a TypeError is raised.

The new collection keeps this collection’s name template unless new_name is given. The original ToneCollection is left unmodified.

Used for tonal transformations such as transposition and inversion.

Examples

>>> from openmusickit.systems.wsmn.tonal.symbols import C, E, G, Gx, B, M3
>>> from openmusickit.systems.wsmn.tonal.tonal_vector import TonalVector, TonalDirection

Transposition, with the interval passed as the operand. Tone order is preserved, and the root is transformed along with the tones:

>>> triad = ToneCollection([C, E, G], root=C, name="{root} major")
>>> up = triad.transform(TonalVector.transpose, M3)
>>> up == ToneCollection([E, Gx, B], root=E)
True
>>> up.name
'E major'
>>> up.transform(TonalVector.transpose, M3, TonalDirection.DOWN) == triad
True

The original is unchanged:

>>> triad == ToneCollection([C, E, G], root=C)
True

A user-defined operation that needs no operand, with a new name:

>>> def sharpen(tv):
...     return tv + TonalVector((0, 1))
>>> sharp = triad.transform(sharpen, new_name="{root} major (sharpened)")
>>> list(sharp)
[TonalVector((0, 1)), TonalVector((2, 5)), TonalVector((4, 8))]
>>> sharp.name
'C♯ major (sharpened)'

A collection with no root works too:

>>> ToneCollection([C, E]).transform(TonalVector.transpose, M3)
ToneCollection([TonalVector((2, 4)), TonalVector((4, 8))], root=None)

An operation that does not produce a Tone is rejected:

>>> triad.transform(str)
Traceback (most recent call last):
...
TypeError: ...