A comprehensive, object model of the Xenakis Sieve. music21.sieve.Sieve objects can be created from high-level string notations, and used to generate line segments in various representation. Additional functionality is available through associated objects.
The music21.sieve.Sieve class permits generation segments in four formats.
>>> a = sieve.Sieve('3@2|7@1')
>>> a.segment()
[1, 2, 5, 8, 11, 14, 15, 17, 20, 22, 23, 26, 29, 32, 35, 36, 38, 41, 43, 44, 47, 50, 53, 56, 57, 59, 62, 64, 65, 68, 71, 74, 77, 78, 80, 83, 85, 86, 89, 92, 95, 98, 99]
>>> a.segment(segmentFormat='binary')
[0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1]
>>> a.segment(segmentFormat='width')
[1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1]
>>> len(a.segment(segmentFormat='unit'))
43
A music21.sieve.CompressionSegment can be used to derive a Sieve from any sequence of integers.
>>> a = sieve.CompressionSegment([3,4,5,6,7,8,13,19])
>>> str(a)
'6@1|7@6|8@5|9@4|10@3|11@8'
The music21.sieve.PitchSieve class provides a quick generation of music21.pitch.Pitch lists from Sieves.
>>> a = sieve.PitchSieve('13@3|13@6|13@9', 'c1', 'c10', 'f#4')
>>> pitches = a()
>>> ', '.join([str(p) for p in pitches])
'F#1, A1, C2, G2, B-2, C#3, G#3, B3, D4, A4, C5, E-5, B-5, C#6, E6, B6, D7, F7, C8, E-8, F#8, C#9, E9, G9'
Treat a sequence of integers as defining contiguous binary integers, where provided values are 1’s and excluded values are zero.
For instance, running [3,10,12] through this method gives a 1 for the first entry (signifying 3), 0s for the next six entries (signifying 4-9), a 1 (for 10), a 0 (for 11), and a 1 (for 12).
>>> sieve.discreteBinaryPad([3,10,12])
[1, 0, 0, 0, 0, 0, 0, 1, 0, 1]
>>> sieve.discreteBinaryPad([3,4,5])
[1, 1, 1]
Yields the sequence of prime numbers via the Sieve of Eratosthenes. rather than creating a fixed list of a range (z) and crossing out multiples of sequential candidates, this algorithm stores primes under their next possible candidate, thus allowing the generation of primes in sequence without storing a complete range (z).
create a dictionary. each entry in the dictionary is a key:item pair of the largest (key) largest multiple of this prime so far found : (item) the prime. the dictionary only has as many entries as found primes.
if a candidate is not a key in the dictionary, it is not a multiple of any already-found prime; it is thus a prime. a new entry is added to the dictionary, with the square of the prime as the key. the square of the prime is the next possible multiple to be found.
to use this generator, create an instance and then call the .next() method on the instance
>>> a = sieve.eratosthenes()
>>> next(a)
2
>>> next(a)
3
We can also specify a starting value for the sequence, skipping over initial primes smaller than this number:
>>> a = sieve.eratosthenes(95)
>>> next(a)
97
>>> next(a)
101
Returns true if an integer is likely prime or false if it is likely composite using the Rabin Miller primality test.
See also here: http://www.4dsolutions.net/ocn/numeracy2.html
>>> sieve.rabinMiller(234)
False
>>> sieve.rabinMiller(5)
True
>>> sieve.rabinMiller(4)
False
>>> sieve.rabinMiller(123986234193)
False
Given a certain number of parts, return a list unit-interval values between 0 and 1, with as many divisions as parts; 0 and 1 are always inclusive.
>>> sieve.unitNormEqual(3)
[0.0, 0.5, 1]
If parts is 0 or 1, then a single entry of [0] is given:
>>> sieve.unitNormEqual(1)
[0]
Given a list of numbers, create a proportional spacing across the unit interval.
The first entry will always be 0 and the last 1, other entries will be spaced according to their distance between these two units. For instance, for 0, 3, 4 the middle entry will be 0.75 since 3 is 3/4 of the distance between 0 and 4:
>>> sieve.unitNormRange([0,3,4])
[0.0, 0.75, 1.0]
but for [1, 3, 4], it will be .666... because 3 is 2/3 of the distance between 1 and 4
>>> sieve.unitNormRange([1,3,4])
[0.0, 0.666..., 1.0]
Given a step size and an a/b min/max range, calculate number of parts to fill step through inclusive a,b, then return a unit interval list of values necessary to cover region.
Note that returned values are by default normalized within the unit interval.
>>> sieve.unitNormStep(.5, 0, 1)
[0.0, 0.5, 1]
>>> sieve.unitNormStep(.5, -1, 1)
[0.0, 0.25, 0.5, 0.75, 1]
>>> sieve.unitNormStep(.5, -1, 1, normalized=False)
[-1, -0.5, 0.0, 0.5, 1.0]
>>> post = sieve.unitNormStep(.25, 0, 20)
>>> len(post)
81
>>> post = sieve.unitNormStep(.25, 0, 20, normalized=False)
>>> len(post)
81
Utility to convert from a point sequence to sieve.
A z range can be supplied to explicitly provide the complete sieve segment, both positive and negative values. all values in the z range not in the segment are interepreted as negative values. thus, there is an essential dependency on the z range and the realized sieve.
No matter the size of the z range, there is a modulus at which one point in the segment can be found. As such, any segment can be reduced to, at a mimimum, a residual for each point in the segment, each, for the supplied z, providing a segment with one point.
The same segment can then have multipled logical string representations, depending on the provided z.
Quick utility generation of music21.pitch.Pitch lists from music21.sieve.Sieve objects.
>>> ps = sieve.PitchSieve('6@0', 'c4', 'c8')
>>> [str(p) for p in ps()]
['C4', 'F#4', 'C5', 'F#5', 'C6', 'F#6', 'C7', 'F#7', 'C8']
PitchSieve methods
Return a list of Interval objects that defines the complete structure of this music21.sieve.Sieve.
>>> a = sieve.PitchSieve('3@0')
>>> a.getIntervalSequence()
[<music21.interval.Interval m3>]
>>> a = sieve.PitchSieve('3@0|7@0')
>>> a.sieveObject.segment()
[0, 3, 6, 7, 9, 12, 14, 15, 18, 21, 24, 27, 28, 30, 33, 35, 36, 39, 42, 45, 48, 49, 51, 54, 56, 57, 60, 63, 66, 69, 70, 72, 75, 77, 78, 81, 84, 87, 90, 91, 93, 96, 98, 99]
>>> a.sieveObject.period()
21
>>> a.getIntervalSequence()
[<music21.interval.Interval m3>, <music21.interval.Interval m3>, <music21.interval.Interval m2>, <music21.interval.Interval M2>, <music21.interval.Interval m3>, <music21.interval.Interval M2>, <music21.interval.Interval m2>, <music21.interval.Interval m3>, <music21.interval.Interval m3>]
>>> b = sieve.PitchSieve('(-3@2 & 4) | (-3@1 & 4@1) | (3@2 & 4@2) | (-3 & 4@3)') # major scale
>>> b.getIntervalSequence()
[<music21.interval.Interval M2>, <music21.interval.Interval M2>, <music21.interval.Interval m2>, <music21.interval.Interval M2>, <music21.interval.Interval M2>, <music21.interval.Interval M2>, <music21.interval.Interval m2>]
object that represents a modulus and a start point each object stores a range of integers (self._z) from which sections are drawn this range of integers can be changed whenever the section os drawn
Residual methods
period is M; obvious, but nice for completeness
>>> a = sieve.Residual(3, 2)
>>> a.period()
3
does not show any logical operator but unary negation
get a residual subset of this modulus at this n within the integer range provided by z format can be ‘int’ or ‘bin’, for integer or binary
>>> a = sieve.Residual(3, 2)
>>> a.segment(3)
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]
>>> a.segment(3, range(3,15))
[5, 8, 11, 14]
z is the range of integers to use when generating a list
z is the range of integers to use when generating a list convenience functiont that fixes max
Create a sieve segment from a sieve logical string of any complexity.
Sieve methods
Collect sieve segment points for the provided length and format.
>>> a = sieve.Sieve('3@11')
>>> a.collect(10, 100, 10, 'int')
[102, 105, 108, 111, 114, 117, 120, 123, 126, 129]
Set this sieve to its compressed state.
Set this Sieve to its expanded state.
Return the period of the sieve.
>>> a = sieve.Sieve('3@11')
>>> a.period()
3
>>> b = sieve.Sieve('2&4&8|5')
>>> b.period()
40
>>> c = sieve.Sieve('(5|2)&4&8')
>>> c.period()
40
style of None is use for users; adds | to singel residuals style abs (absolute) does not add | tos single residual class
Return a sieve segment in various formats.
>>> a = sieve.Sieve('3@11')
>>> a.segment('exp')
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]
>>> c = sieve.Sieve('(5|2)&4&8')
>>> c.segment('cmp', segmentFormat='wid')
[8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]
Set the z as a list. The z is the range of integers to use when generating a sieve segment.
Set the z as a min and max value. The z is the range of integers to use when generating a sieve segment.