Improve docstrings for Sphinx documentation
This commit is contained in:
parent
42d4cfb427
commit
64dd35e1f8
4 changed files with 238 additions and 82 deletions
|
|
@ -28,6 +28,7 @@ release = '0.1'
|
|||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.viewcode',
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ setclass module
|
|||
|
||||
.. automodule:: setclass.setclass
|
||||
:members:
|
||||
:special-members: __init__
|
||||
:member-order: bysource
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# Main requirements
|
||||
-r requirements.txt
|
||||
|
||||
# Code lint
|
||||
|
|
@ -14,5 +15,6 @@ tox
|
|||
|
||||
# Documentation
|
||||
sphinx
|
||||
sphinx_rtd_theme
|
||||
sphinx-rtd-theme
|
||||
sphinxcontrib-napoleon
|
||||
myst-parser
|
||||
|
|
|
|||
|
|
@ -6,18 +6,32 @@ import re
|
|||
|
||||
class SetClass(list):
|
||||
"""
|
||||
Musical set class, containing zero or more pitch classes.
|
||||
Musical set class, containing zero or more pitch classes. This implementation can handle set
|
||||
classes of any arbitrary :attr:`tonality`, or number of divisions of the octave.
|
||||
"""
|
||||
|
||||
def __init__(self, *args: int, tonality: int = 12) -> None:
|
||||
"""
|
||||
Instantiate a Class Set with a series of integers. Each pitch class is "normalised" by
|
||||
modulo the tonality; the set is sorted in ascending order; and values "rotated" until the
|
||||
lowest value is 0. For a number of divisions of the octave other than the default (Western
|
||||
harmony) value of 12, supply an integer value using the 'tonality' keyword. Example:
|
||||
Instantiate a :class:`ClassSet` object with a series of integers.
|
||||
|
||||
sc = SetClass(0, 7, 9)
|
||||
sc = SetClass(0, 2, 3, tonality=7)
|
||||
Each supplied pitch class is "normalised" by modulo the :attr:`tonality`, the set is
|
||||
sorted in ascending order, and values are transposed (rotated) until the lowest value is 0.
|
||||
For a number of divisions of the octave other than the default (Western harmony) value of
|
||||
12, supply an integer value using the 'tonality' keyword. Example:
|
||||
|
||||
>>> sc1 = SetClass(0, 7, 9)
|
||||
>>> sc1
|
||||
SetClass{0,7,9}
|
||||
>>> sc2 = SetClass(0, 2, 3, tonality=7)
|
||||
>>> sc2
|
||||
SetClass{0,2,3} (T=7)
|
||||
|
||||
Args:
|
||||
*args (int):
|
||||
The pitch class values.
|
||||
tonality (int):
|
||||
The :attr:`tonality`, or modulus, is the number of divisions of the octave.
|
||||
If unspecified, the default value of 12 is assumed (Western harmony).
|
||||
"""
|
||||
self._tonality = tonality
|
||||
|
||||
|
|
@ -39,48 +53,60 @@ class SetClass(list):
|
|||
super().append(i)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return the Python instance string representation."""
|
||||
"""Return a string representation of this instance."""
|
||||
s = f"SetClass{{{','.join(str(i) for i in self.pitch_classes)}}}"
|
||||
return s if self.tonality == 12 else f"{s} (T={self.tonality})"
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Return a unique identifier for the instance, based on the :attr:`pitch_classes` used."""
|
||||
return sum([hash(i) for i in self.pitch_classes])
|
||||
|
||||
@property
|
||||
def pitch_classes(self) -> list(int):
|
||||
"""The pitch classes as an ordered :class:`list` of integers."""
|
||||
return list(self)
|
||||
|
||||
@cached_property
|
||||
def tonality(self) -> int:
|
||||
"""
|
||||
Returns the number of (equal) divisions of the octave. The default value is 12, which
|
||||
The number of (equal) divisions of the octave. The default value is 12, which
|
||||
represents traditional Western chromatic harmony, the octave divided into twelve semitones.
|
||||
"""
|
||||
return self._tonality
|
||||
|
||||
@cached_property
|
||||
def cardinality(self) -> int:
|
||||
"""Returns the cardinality of the set class, i.e. the number of pitch classes."""
|
||||
"""
|
||||
The cardinality of the set class, i.e. the number of :attr:`pitch_classes`.
|
||||
"""
|
||||
return len(self.pitch_classes)
|
||||
|
||||
@cached_property
|
||||
def brightness(self) -> int:
|
||||
"""Returns the brightness of the set class, defined as the sum of the pitch class values."""
|
||||
"""
|
||||
The brightness of the set class.
|
||||
|
||||
Brightness (B) is a property proposed by Brian Leonard, defined as the sum of the values of
|
||||
the :attr:`pitch_classes`.
|
||||
"""
|
||||
return sum(self.pitch_classes)
|
||||
|
||||
@cached_property
|
||||
def decimal(self) -> int:
|
||||
"""
|
||||
The decimal value of the binary representation of the :attr:`pitch_classes`.
|
||||
|
||||
Returns the decimal value of the pitch classes expressed as a binary bit mask, i.e. the sum
|
||||
of 2ⁱ where i is each pitch class value. For example, {0,1,4,6} has a binary value of
|
||||
000001010011, which is the decimal value 83.
|
||||
— Goyette (2012) p. 25, citing Brinkman (1986).
|
||||
of 2ⁱ where i is each pitch class value. For example, set class {0,1,4,6} has a binary value
|
||||
of 000001010011, which is the decimal value 83.
|
||||
|
||||
Further reading: Goyette (2012) p. 25, citing Brinkman (1986).
|
||||
"""
|
||||
return sum([2**i for i in self.pitch_classes])
|
||||
|
||||
@cached_property
|
||||
def adjacency_intervals(self) -> list(int):
|
||||
"""Adjacency intervals between the pitch classes, used for Leonard notation subscripts."""
|
||||
"""The ordered :class:`list` of adjacency intervals between the pitch classes."""
|
||||
if not self.pitch_classes:
|
||||
return list()
|
||||
intervals = list()
|
||||
|
|
@ -95,7 +121,14 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def z_relations(self) -> list:
|
||||
"""
|
||||
Return all distinct set classes with the same interval vector (Allen Forte: "Z-related").
|
||||
A :class:`list` of the Z-relations of this set class.
|
||||
|
||||
Allen Forte in his book *The Structure of Atonal Music* (1973) described the relationship
|
||||
between twins of set classes that share the same :attr:`interval_vector`, but are not
|
||||
related by :attr:`inversion`, :attr:`complement`, or transposition (rotation), as Z-related
|
||||
('Z' for *zygote* from Greek: ζυγωτός, 'joined'). This property returns all distinct set
|
||||
classes with the same interval vector.
|
||||
|
||||
For example, Forte 4-Z15 {0,1,4,6} and Forte 4-Z29 {0,1,3,7} both have iv⟨1,1,1,1,1,1⟩ but
|
||||
are not inversions, complements, or transpositions (rotations) of each other.
|
||||
"""
|
||||
|
|
@ -104,40 +137,66 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def interval_vector(self) -> list:
|
||||
"""
|
||||
An ordered tuple containing the multiplicities of each interval class in the set class.
|
||||
Denoted in angle-brackets, e.g.
|
||||
The interval vector of {0,2,4,5,7,9,11} is ⟨2,5,4,3,6,1⟩
|
||||
— Rahn (1980), p. 100
|
||||
An ordered :class:`list` containing the multiplicities of each interval class in the set
|
||||
class. Denoted in angle-brackets, e.g. the interval vector of {0,2,4,5,7,9,11} is
|
||||
⟨2,5,4,3,6,1⟩. Each element in the vector is the frequency of occurrence of the interval
|
||||
represented by its ordinal position, i.e. ⟨2,5,4,3,6,1⟩ means two semitones, five major
|
||||
seconds, four minor thirds, and so on. — Rahn (1980), p. 100.
|
||||
"""
|
||||
from itertools import combinations
|
||||
iv = [0 for i in range(1, int(self.tonality / 2) + 1)]
|
||||
for (a, b) in combinations(self.pitch_classes, 2):
|
||||
ic = SetClass.unordered_interval(a, b)
|
||||
ic = self.unordered_interval(a, b)
|
||||
iv[ic - 1] += 1
|
||||
return iv
|
||||
|
||||
def ordered_interval(a: int, b: int) -> int:
|
||||
def ordered_interval(self, a: int, b: int) -> int:
|
||||
"""
|
||||
The ordered interval or "directed interval" (Babbitt) of two pitch classes is determined by
|
||||
the difference of the pitch class values, modulo 12:
|
||||
i⟨a,b⟩ = b-a mod 12 — Rahn (1980), p. 25
|
||||
"""
|
||||
return (b % 12 - a % 12) % 12
|
||||
Return the ordered interval of two pitch classes.
|
||||
|
||||
def unordered_interval(a: int, b: int) -> int:
|
||||
The ordered interval, or "directed interval" (Babbitt) of two :attr:`pitch_classes` is
|
||||
determined by the difference of the pitch class values, modulo :attr:`tonality`. For example
|
||||
with tonality 12:
|
||||
|
||||
i⟨a,b⟩ = b-a mod 12
|
||||
|
||||
— Rahn (1980), p. 25
|
||||
|
||||
Args:
|
||||
a (int): the first pitch class value.
|
||||
b (int): the second pitch class value.
|
||||
|
||||
Returns:
|
||||
The ordered interval as ann integer.
|
||||
"""
|
||||
return (b % self.tonality - a % self.tonality) % self.tonality
|
||||
|
||||
def unordered_interval(self, a: int, b: int) -> int:
|
||||
"""
|
||||
Return the unordered interval of two pitch classes.
|
||||
|
||||
The unordered interval (also "interval distance", "interval class", "ic", or "undirected
|
||||
interval") of two pitch classes is the smaller of the two possible ordered intervals
|
||||
(differences in pitch class value):
|
||||
i(a,b) = min: i⟨a,b⟩, i⟨b,a⟩ — Rahn (1980), p. 28
|
||||
interval") of two :attr:`pitch_classes` is the smaller of the possible values of
|
||||
:attr:`ordered_interval` (differences in pitch class value):
|
||||
|
||||
i(a,b) = min: i⟨a,b⟩, i⟨b,a⟩
|
||||
|
||||
— Rahn (1980), p. 28
|
||||
|
||||
Args:
|
||||
a (int): the first pitch class value.
|
||||
b (int): the second pitch class value.
|
||||
|
||||
Returns:
|
||||
The ordered interval as ann integer.
|
||||
"""
|
||||
return min(SetClass.ordered_interval(a, b), SetClass.ordered_interval(b, a))
|
||||
return min(self.ordered_interval(a, b), self.ordered_interval(b, a))
|
||||
|
||||
@cached_property
|
||||
def versions(self) -> list(SetClass):
|
||||
"""
|
||||
Returns all possible zero-normalised versions (clock rotations) of this set class,
|
||||
sorted by brightness. See Rahn (1980) Set types, Tₙ
|
||||
All possible zero-normalised transpositions (rotations) of this set class, sorted by
|
||||
:attr:`brightness`. See Rahn (1980), Tₙ set types.
|
||||
"""
|
||||
# The empty set class has one version, itself
|
||||
if not self.pitch_classes:
|
||||
|
|
@ -154,9 +213,13 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def rahn_normal_form(self) -> SetClass:
|
||||
"""
|
||||
Return the Rahn normal form of the set class; Leonard describes this as "most dispersed from
|
||||
the right". Find the smallest outside interval, and proceed inwards from the right until one
|
||||
result remains. See Rahn (1980), p. 33
|
||||
The Rahn normal form of the set class.
|
||||
|
||||
John Rahn's normal form described in his book *Basic Atonal Theory* (1980) is an algorithm
|
||||
to produce a unique form for each set class (see :attr:`rahn_normal_form`). Often wrongly
|
||||
described as "most packed to the left", Leonard describes it as "most dispersed from the
|
||||
right". Find the smallest outside interval, and if necessary proceed inwards from the right
|
||||
finding the smallest next interval until one result remains. See Rahn (1980), p. 33.
|
||||
"""
|
||||
def _most_dispersed(versions, n):
|
||||
return [i for i in versions if i.pitch_classes[-n] == min([i.pitch_classes[-n] for i in versions])]
|
||||
|
|
@ -171,8 +234,8 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def packed_left(self) -> SetClass:
|
||||
"""
|
||||
Return the form of the set class that is most packed to the left (smallest adjacency
|
||||
intervals to the left). Find the smallest adjacency interval, and proceed towards the right
|
||||
The form of the set class that is most packed to the left (the smallest adjacency intervals
|
||||
to the left). Find the smallest first adjacency interval, and proceed towards the right
|
||||
until one result remains.
|
||||
"""
|
||||
def _most_packed(versions, n):
|
||||
|
|
@ -188,11 +251,12 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def prime_form(self) -> SetClass:
|
||||
"""
|
||||
Return the prime form of the set class. Find the forms with the smallest outside interval,
|
||||
and if necessary chose the form most packed to the left (the smallest adjacency intervals
|
||||
working from left to right).
|
||||
Allen Forte describes the algorithm in his book *The Structure of Atonal Music* (1973) in
|
||||
section 1.2 (pp. 3-5), citing Milton Babbitt (1961).
|
||||
Return the prime form of the set class.
|
||||
|
||||
Allen Forte describes the algorithm for finding this normal form in his book *The Structure
|
||||
of Atonal Music* (1973) in section 1.2 (pp. 3-5), citing Milton Babbitt (1961). Find the
|
||||
forms with the smallest outside interval, and if necessary chose the form most packed to the
|
||||
left (the smallest adjacency intervals working from left to right).
|
||||
"""
|
||||
def _most_packed(versions, n):
|
||||
return [i for i in versions if i.pitch_classes[n] == min([i.pitch_classes[n] for i in versions])]
|
||||
|
|
@ -211,7 +275,8 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def darkest_form(self) -> SetClass:
|
||||
"""
|
||||
Returns the version with the smallest brightness value, most packed to the left.
|
||||
The version of this set class with the smallest :attr:`brightness` value, most packed to the
|
||||
left.
|
||||
"""
|
||||
if not self.versions:
|
||||
return self
|
||||
|
|
@ -233,7 +298,7 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def brightest_form(self) -> SetClass:
|
||||
"""
|
||||
Returns the version with the largest brightness value.
|
||||
The version of this set class with the largest :attr:`brightness` value.
|
||||
TODO: How to break a tie? Or return all matches in a tuple? Sorted by what?
|
||||
"""
|
||||
return self.versions[-1] if self.versions else self
|
||||
|
|
@ -241,15 +306,16 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def inversion(self) -> SetClass:
|
||||
"""
|
||||
Returns the inversion of this set class, equivalent of reflection through the 0 axis on a
|
||||
clock diagram.
|
||||
The inversion of this set class, transposed so the smallest pitch class is 0. Equivalent to
|
||||
a reflection through the 0 axis on a clock diagram.
|
||||
"""
|
||||
return SetClass(*[self.tonality - i for i in self.pitch_classes], tonality=self.tonality)
|
||||
|
||||
@cached_property
|
||||
def is_symmetrical(self) -> bool:
|
||||
"""
|
||||
Returns whether this set class is symmetrical upon inversion, for example Forte 5-Z17:
|
||||
Whether this set class is symmetrical upon inversion, for example Forte 5-Z17:
|
||||
|
||||
{0,1,2,5,9} → {0,4,8,9,11}
|
||||
"""
|
||||
return self.darkest_form == self.inversion.darkest_form
|
||||
|
|
@ -257,34 +323,45 @@ class SetClass(list):
|
|||
@cached_property
|
||||
def complement(self) -> SetClass:
|
||||
"""
|
||||
Returns the set class containing all pitch classes absent in this one (rotated so the
|
||||
smallest is 0).
|
||||
The set class containing all :attr:`pitch_classes` absent in this one, transposed so the
|
||||
smallest pitch class is 0.
|
||||
"""
|
||||
return SetClass(*[i for i in range(self.tonality) if i not in self.pitch_classes], tonality=self.tonality)
|
||||
|
||||
@cached_property
|
||||
def dozenal_notation(self) -> str:
|
||||
"""
|
||||
If tonality is no greater than 12, return a string representation using Dozenal Society
|
||||
characters '↊' for 10 and '↋' for 11 (the Pitman forms from Unicode 8.0 release, 2015).
|
||||
A string representation using ↊ and ↋ for 10 and 11.
|
||||
|
||||
For a set class with a :attr:`tonality` no greater than 12, this property replaces the 10
|
||||
and 11 pitch classes with the Dozenal Society characters '↊' and '↋' respectively. These are
|
||||
the Pitman forms from the Unicode 8.0 specification released in 2015.
|
||||
"""
|
||||
return f"{self}" if self.tonality > 12 else f"{self}".replace('10', '↊').replace('11', '↋')
|
||||
|
||||
@cached_property
|
||||
def duodecimal_notation(self) -> str:
|
||||
"""
|
||||
If tonality is no greater than 12, replace 10 and 11 with 'T' and 'E'.
|
||||
A string representation using T and E for 10 and 11.
|
||||
|
||||
For a set class with a :attr:`tonality` no greater than 12, this property replaces the 10
|
||||
and 11 pitch classes with the letters 'T' and 'E' respectively.
|
||||
"""
|
||||
return f"{self}" if self.tonality > 12 else f"{self}".replace('10', 'T').replace('11', 'E')
|
||||
|
||||
@cached_property
|
||||
def leonard_notation(self) -> str:
|
||||
"""
|
||||
Returns a string representation of this set class using subscripts to denote the adjacency
|
||||
intervals between the pitch classes instead of commas, and the overall brightness (sum of
|
||||
pitch class values) denoted as a superscript. In standard tonality (T=12) the letters T and
|
||||
E are used for pitch classes 10 and 11. For example, Forte 7-34, {0,1,3,4,6,8,10} is
|
||||
notated [0₁1₂3₁4₂6₂8₂T₂]⁽³²⁾.
|
||||
The string representation proposed by Brian Leonard.
|
||||
|
||||
Returns a string representation of this set class using subscripts to denote the
|
||||
:attr:`adjacency_intervals` between the pitch classes instead of commas, and the overall
|
||||
:attr:`brightness` (sum of the values of :attr:`pitch_classes`) denoted as a superscript.
|
||||
In standard tonality (T=12) the letters T and E are used for pitch classes 10 and 11. For
|
||||
example, Forte 7-34 would be written as [0₁1₂3₁4₂6₂8₂T₂]⁽³²⁾ in this scheme:
|
||||
|
||||
>>> SetClass.from_string('{0,1,3,4,6,8,10}').leonard_notation
|
||||
[0₁1₂3₁4₂6₂8₂T₂]⁽³²⁾
|
||||
"""
|
||||
# Return numbers as subscript and superscript strings:
|
||||
def subscript(n: int) -> str:
|
||||
|
|
@ -307,17 +384,49 @@ class SetClass(list):
|
|||
@classmethod
|
||||
def from_string(this, string: str, tonality: int = 12) -> SetClass:
|
||||
"""
|
||||
Attempt to create a SetClass from any string containing a sequence of zero or more integers.
|
||||
A useful convenience function, e.g. SetClass.from_string('{0,3,7,9}')
|
||||
Create a :class:`SetClass` from a string.
|
||||
|
||||
A useful convenience function for converting from various text representations of set
|
||||
classes that contain a sequence of zero or more integers. Non-integer content is ignored,
|
||||
and integers must be separated by some non-integer character(s), usually a space, comma, or
|
||||
similar. For instance:
|
||||
|
||||
>>> SetClass.from_string("Prélude à l'après-midi d'un faune uses [0,2,4,6,8,10]")
|
||||
SetClass{0,2,4,6,8,10}
|
||||
>>> SetClass.from_string('{0, 3, 7}', tonality=8)
|
||||
SetClass{0,3,7} (T=8)
|
||||
|
||||
Args:
|
||||
string (str):
|
||||
Any string representation of a set class, containing some integer content.
|
||||
tonality (int):
|
||||
The :attr:`tonality`, or modulus, is the number of divisions of the octave.
|
||||
If unspecified, the default value of 12 is assumed (Western harmony).
|
||||
|
||||
Returns:
|
||||
A :class:`SetClass` instance with the pitch classes found in the string.
|
||||
"""
|
||||
return SetClass(*re.findall(r'\d+', string), tonality=tonality)
|
||||
|
||||
@classmethod
|
||||
def all_of_cardinality(cls, cardinality: int, tonality: int = 12) -> set:
|
||||
def all_of_cardinality(this, cardinality: int, tonality: int = 12) -> set:
|
||||
"""
|
||||
Returns all set classes of a given cardinality. Tonality can be specified, default is 12.
|
||||
Warning: high values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
Returns a :class:`set` of all possible :class:`SetClass` objects with a given
|
||||
:attr:`cardinality`.
|
||||
|
||||
.. warning:: High values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
|
||||
Args:
|
||||
cardinality (int):
|
||||
The :attr:`cardinality` of the set classes to return.
|
||||
tonality (int):
|
||||
The :attr:`tonality`, or modulus, is the number of divisions of the octave.
|
||||
If unspecified, the default value of 12 is assumed (Western harmony).
|
||||
|
||||
Returns:
|
||||
A :class:`set` of :class:`SetClass` objects.
|
||||
|
||||
"""
|
||||
def _powerset(seq):
|
||||
"""Set of all possible unique subsets."""
|
||||
|
|
@ -330,32 +439,68 @@ class SetClass(list):
|
|||
return set(SetClass(*i, tonality=tonality) for i in _powerset(range(tonality)) if len(i) == cardinality and 0 in i)
|
||||
|
||||
@classmethod
|
||||
def darkest_of_cardinality(this, cardinality: int, tonality: int = 12, prime: bool = False) -> set:
|
||||
def darkest_of_cardinality(this, cardinality: int, tonality: int = 12) -> set:
|
||||
"""
|
||||
Returns all set classes of a given cardinality, in their darkest forms (ignore rotations).
|
||||
Tonality can be specified, default is 12.
|
||||
Warning: high values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
Returns a :class:`set` of all :class:`SetClass` objects with a given :attr:`cardinality` in
|
||||
their darkest forms.
|
||||
|
||||
This produces a smaller set than :attr:`all_of_cardinality`, since it eliminates set classes
|
||||
that are "brighter" transpositions (rotations) of the darkest :class:`SetClass` returned by
|
||||
the :attr:`darkest_form` property.
|
||||
|
||||
.. warning:: High values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
|
||||
Args:
|
||||
cardinality (int):
|
||||
The :attr:`cardinality` of the set classes to return.
|
||||
tonality (int):
|
||||
The :attr:`tonality`, or modulus, is the number of divisions of the octave.
|
||||
If unspecified, the default value of 12 is assumed (Western harmony).
|
||||
|
||||
Returns:
|
||||
A :class:`set` of :class:`SetClass` objects in :attr:`darkest_form`.
|
||||
"""
|
||||
return set(i.darkest_form for i in this.all_of_cardinality(cardinality, tonality))
|
||||
|
||||
@classmethod
|
||||
def normal_of_cardinality(this, cardinality: int, tonality: int = 12, prime: bool = False) -> set:
|
||||
def normal_of_cardinality(this, cardinality: int, tonality: int = 12) -> set:
|
||||
"""
|
||||
Returns all set classes of a given cardinality, in their (darkest) Rahn normal forms (ignore
|
||||
rotations). Tonality can be specified, default is 12.
|
||||
Warning: high values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
Returns a :class:`set` of all :class:`SetClass` objects with a given :attr:`cardinality` in
|
||||
their Rahn normal form.
|
||||
|
||||
This produces a smaller set than :attr:`all_of_cardinality`, since it eliminates set classes
|
||||
that are transpositions (rotations) of the normalised :class:`SetClass` returned by the
|
||||
:attr:`rahn_normal_form` property.
|
||||
|
||||
.. warning:: High values of tonality can take a long time to calculate (T=24 takes about a
|
||||
minute on an Intel i7-13700H CPU).
|
||||
|
||||
Args:
|
||||
cardinality (int):
|
||||
The :attr:`cardinality` of the set classes to return.
|
||||
tonality (int):
|
||||
The :attr:`tonality`, or modulus, is the number of divisions of the octave.
|
||||
If unspecified, the default value of 12 is assumed (Western harmony).
|
||||
|
||||
Returns:
|
||||
A :class:`set` of :class:`SetClass` objects in :attr:`rahn_normal_form`.
|
||||
"""
|
||||
return set(i.rahn_normal_form for i in this.all_of_cardinality(cardinality, tonality))
|
||||
|
||||
@classmethod
|
||||
def bright_rahn_normal_forms(this) -> set:
|
||||
"""
|
||||
The set of Rahn normal forms that are not the same as the darkest form.
|
||||
|
||||
John Rahn's normal form from *Basic Atonal Theory* (1980) is an algorithm to produce a
|
||||
unique form for each set class. Most of the time it is also the "darkest" (smallest
|
||||
brightness value), except for all the times when that is not the case; this function returns
|
||||
that list, as a set of (cardinality, darkest, rahn) tuples.
|
||||
unique form for each set class (see :attr:`rahn_normal_form`). Most of the time it is also
|
||||
the same as the :attr:`darkest_form` (that with the smallest :attr:`brightness` value),
|
||||
except for all the times when that is not the case!
|
||||
|
||||
Returns:
|
||||
A :class:`set` of (:attr:`cardinality`, :attr:`darkest_form`, :attr:`rahn_normal_form`)
|
||||
tuples.
|
||||
"""
|
||||
cases = set()
|
||||
for C in range(13): # 0 to 12
|
||||
|
|
@ -367,12 +512,18 @@ class SetClass(list):
|
|||
@classmethod
|
||||
def bright_prime_forms(this) -> set:
|
||||
"""
|
||||
The set of Forte prime forms that are not the same as the darkest form.
|
||||
|
||||
Allen Forte describes the algorithm for deriving the "prime" or zeroed normal form, in his
|
||||
book *The Structure of Atonal Music* (1973) in section 1.2 (pp. 3-5), citing Milton Babbitt
|
||||
(1961). It produces a unique form for each set class, which most of the time is also the
|
||||
"darkest" (smallest brightness value), except for all the times when that is not the case;
|
||||
this function returns that list, as a set of (cardinality, darkest, prime) tuples.
|
||||
(1961). It produces a unique form for each set class (see :attr:`prime_form`), which most of
|
||||
the time is the same as the :attr:`darkest_form` (that with the smallest :attr:`brightness`
|
||||
value), except for all the times when that is not the case!
|
||||
|
||||
Returns:
|
||||
A :class:`set` of (:attr:`cardinality`, :attr:`darkest_form`, :attr:`prime_form`) tuples.
|
||||
"""
|
||||
|
||||
cases = set()
|
||||
for C in range(13): # 0 to 12
|
||||
for sc in this.all_of_cardinality(C):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue