def with_power_of_two_denominator(self, contents_multiplier=durationtools.Multiplier(1)): r"""Makes new time signature equivalent to current time signature with power-of-two denominator. >>> time_signature = TimeSignature((3, 12)) :: >>> time_signature.with_power_of_two_denominator() TimeSignature((2, 8)) Returns new time signature. """ # check input contents_multiplier = durationtools.Multiplier(contents_multiplier) # save non_power_of_two time_signature and denominator non_power_of_two_denominator = self.denominator # find power_of_two denominator if contents_multiplier == durationtools.Multiplier(1): power_of_two_denominator = mathtools.greatest_power_of_two_less_equal(non_power_of_two_denominator) else: power_of_two_denominator = mathtools.greatest_power_of_two_less_equal(non_power_of_two_denominator, 1) # find power_of_two pair non_power_of_two_pair = mathtools.NonreducedFraction(self.pair) power_of_two_pair = non_power_of_two_pair.with_denominator(power_of_two_denominator) # return new power_of_two time signature return type(self)(power_of_two_pair)
def with_power_of_two_denominator( self, contents_multiplier=1, ) -> 'TimeSignature': """ Makes new time signature equivalent to current time signature with power-of-two denominator. .. container:: example Non-power-of-two denominator with power-of-two denominator: >>> time_signature = abjad.TimeSignature((3, 12)) >>> time_signature.with_power_of_two_denominator() TimeSignature((2, 8)) """ contents_multiplier = Multiplier(contents_multiplier) contents_multiplier = Multiplier(contents_multiplier) non_power_of_two_denominator = self.denominator if contents_multiplier == Multiplier(1): power_of_two_denominator = \ mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator) else: power_of_two_denominator = \ mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator, 1) non_power_of_two_pair = NonreducedFraction(self.pair) power_of_two_fraction = non_power_of_two_pair.with_denominator( power_of_two_denominator) power_of_two_pair = power_of_two_fraction.pair return type(self)(power_of_two_pair)
def make_click_voice_lines(meter_voice_lines): click_voice_lines = [] prev_line = None prev_prev_line = None for line in meter_voice_lines: if 'MeterVoice' in line: click_voice_lines.append('\t\t\\new DrumStaff { \\drummode {\n') elif 's1 *' in line: if r'\time' in prev_line: meter = prev_line.split(' ')[-1] elif r'\time' in prev_prev_line: meter = prev_prev_line.split(' ')[-1] else: raise Exception('can not find LilyPond time directive.') numerator, denominator = meter.split('/') numerator = int(numerator) denominator = int(denominator) denominator = mathtools.greatest_power_of_two_less_equal(denominator) replacement_line = 4 * '\t' + 'ss%s [ %s]\n' % ( denominator, (numerator - 1) * 'mar ') click_voice_lines.append(replacement_line) else: click_voice_lines.append(line) prev_prev_line = prev_line prev_line = line click_voice_lines.append('\t\t}\n') return click_voice_lines
def _scale(self, multiplier=None): from abjad.tools import indicatortools if multiplier is None: return multiplier = durationtools.Multiplier(multiplier) old_time_signature = self.time_signature if mathtools.is_nonnegative_integer_power_of_two(multiplier) and \ 1 <= multiplier: old_numerator = old_time_signature.numerator old_denominator = old_time_signature.denominator new_denominator = old_denominator // multiplier.numerator pair = (old_numerator, new_denominator) new_time_signature = indicatortools.TimeSignature(pair) else: old_denominator = old_time_signature.denominator old_duration = old_time_signature.duration new_duration = multiplier * old_duration new_time_signature = \ self._duration_and_possible_denominators_to_time_signature( new_duration, [old_denominator], multiplier.denominator, ) detach(indicatortools.TimeSignature, self) attach(new_time_signature, self) contents_multiplier_denominator = \ mathtools.greatest_power_of_two_less_equal(multiplier.denominator) pair = (multiplier.numerator, contents_multiplier_denominator) contents_multiplier = durationtools.Multiplier(*pair) self._scale_contents(contents_multiplier)
def implied_prolation(self): r'''Implied prolation of duration. :: >>> for denominator in range(1, 16 + 1): ... duration = Duration(1, denominator) ... result = duration.implied_prolation ... print('{!s}\t{!s}'.format(duration, result)) ... 1 1 1/2 1 1/3 2/3 1/4 1 1/5 4/5 1/6 2/3 1/7 4/7 1/8 1 1/9 8/9 1/10 4/5 1/11 8/11 1/12 2/3 1/13 8/13 1/14 4/7 1/15 8/15 1/16 1 Returns new multipler. ''' from abjad.tools import durationtools numerator = \ mathtools.greatest_power_of_two_less_equal(self.denominator) return durationtools.Multiplier(numerator, self.denominator)
def _scale(self, multiplier=None): from abjad.tools import containertools from abjad.tools import contexttools from abjad.tools import iterationtools from abjad.tools import timesignaturetools from abjad.tools.scoretools import attach if multiplier is None: return multiplier = durationtools.Multiplier(multiplier) old_time_signature = self.time_signature if mathtools.is_nonnegative_integer_power_of_two(multiplier) and \ 1 <= multiplier: old_numerator = old_time_signature.numerator old_denominator = old_time_signature.denominator new_denominator = old_denominator / multiplier.numerator pair = (old_numerator, new_denominator) new_time_signature = contexttools.TimeSignatureMark(pair) else: old_denominator = old_time_signature.denominator old_duration = old_time_signature.duration new_duration = multiplier * old_duration new_time_signature = \ timesignaturetools.duration_and_possible_denominators_to_time_signature( new_duration, [old_denominator], multiplier.denominator) for mark in self._get_marks(contexttools.TimeSignatureMark): mark.detach() attach(new_time_signature, self) contents_multiplier_denominator = \ mathtools.greatest_power_of_two_less_equal(multiplier.denominator) pair = (multiplier.numerator, contents_multiplier_denominator) contents_multiplier = durationtools.Multiplier(*pair) self._scale_contents(contents_multiplier)
def implied_prolation(self): r'''Gets implied prolation. .. container:: example Gets implied prolation: >>> for denominator in range(1, 16 + 1): ... duration = abjad.Duration(1, denominator) ... result = duration.implied_prolation ... print('{!s}\t{!s}'.format(duration, result)) ... 1 1 1/2 1 1/3 2/3 1/4 1 1/5 4/5 1/6 2/3 1/7 4/7 1/8 1 1/9 8/9 1/10 4/5 1/11 8/11 1/12 2/3 1/13 8/13 1/14 4/7 1/15 8/15 1/16 1 Returns multipler. ''' import abjad numerator = \ mathtools.greatest_power_of_two_less_equal(self.denominator) return abjad.Multiplier(numerator, self.denominator)
def _make_container(self, division): from abjad.tools import rhythmmakertools duration_spelling_specifier = self._get_duration_spelling_specifier() forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration time_signature = indicatortools.TimeSignature(division) implied_prolation = time_signature.implied_prolation numerator, denominator = division.pair denominator = mathtools.greatest_power_of_two_less_equal(denominator) assert mathtools.is_positive_integer_power_of_two(denominator) exponent = self.exponent or 0 denominator_multiplier = 2 ** exponent denominator *= denominator_multiplier unit_duration = durationtools.Duration(1, denominator) if forbidden_written_duration is not None: multiplier = 1 while forbidden_written_duration <= unit_duration: unit_duration /= 2 multiplier *= 2 numerator *= multiplier numerator *= denominator_multiplier notes = scoretools.make_notes(numerator * [0], [unit_duration]) if implied_prolation == 1: result = scoretools.Container(notes) else: multiplier = implied_prolation result = scoretools.Tuplet(multiplier, notes) return result
def _make_container(self, division): from abjad.tools import rhythmmakertools duration_spelling_specifier = self.duration_spelling_specifier if duration_spelling_specifier is None: duration_spelling_specifier = \ rhythmmakertools.DurationSpellingSpecifier() forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration time_signature = indicatortools.TimeSignature(division) implied_prolation = time_signature.implied_prolation numerator, denominator = division.pair denominator = mathtools.greatest_power_of_two_less_equal(denominator) assert mathtools.is_positive_integer_power_of_two(denominator) exponent = self.exponent or 0 denominator_multiplier = 2**exponent denominator *= denominator_multiplier unit_duration = durationtools.Duration(1, denominator) if forbidden_written_duration is not None: multiplier = 1 while forbidden_written_duration <= unit_duration: unit_duration /= 2 multiplier *= 2 numerator *= multiplier numerator *= denominator_multiplier notes = scoretools.make_notes(numerator * [0], [unit_duration]) if implied_prolation == 1: result = scoretools.Container(notes) else: multiplier = implied_prolation result = scoretools.Tuplet(multiplier, notes) return result
def with_power_of_two_denominator( self, contents_multiplier=durationtools.Multiplier(1), ): r'''Makes new time signature equivalent to current time signature with power-of-two denominator. .. container:: example **Example 1.** Non-power-of-two denominator with power-of-two denominator: >>> time_signature = TimeSignature((3, 12)) >>> time_signature.with_power_of_two_denominator() TimeSignature((2, 8)) Returns new time signature. ''' # check input contents_multiplier = durationtools.Multiplier(contents_multiplier) # save non_power_of_two time_signature and denominator non_power_of_two_denominator = self.denominator # find power_of_two denominator if contents_multiplier == durationtools.Multiplier(1): power_of_two_denominator = \ mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator) else: power_of_two_denominator = \ mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator, 1) # find power_of_two pair non_power_of_two_pair = mathtools.NonreducedFraction(self.pair) power_of_two_fraction = non_power_of_two_pair.with_denominator( power_of_two_denominator) power_of_two_pair = power_of_two_fraction.pair # return new power_of_two time signature return type(self)(power_of_two_pair)
def _make_monad(self, division): numerator, talea_denominator = division power_of_two_denominator = \ mathtools.greatest_power_of_two_less_equal(talea_denominator) duration = fractions.Fraction(abs(numerator), talea_denominator) power_of_two_duration = \ fractions.Fraction(abs(numerator), power_of_two_denominator) power_of_two_division = (numerator, power_of_two_denominator) tuplet_multiplier = duration / power_of_two_duration leaves = scoretools.make_leaves([0], [power_of_two_division]) tuplet = scoretools.Tuplet(tuplet_multiplier, leaves) return tuplet
def fill_measures_in_expr_with_time_signature_denominator_notes( expr, iterctrl=None): r'''Fill measures in `expr` with time signature denominator notes: :: >>> staff = Staff([Measure((3, 4), []), Measure((3, 16), []), Measure((3, 8), [])]) >>> scoretools.fill_measures_in_expr_with_time_signature_denominator_notes(staff) .. doctest:: >>> print format(staff) \new Staff { { \time 3/4 c'4 c'4 c'4 } { \time 3/16 c'16 c'16 c'16 } { \time 3/8 c'8 c'8 c'8 } } Delete existing contents of measures in `expr`. Returns none. ''' from abjad.tools import scoretools if iterctrl is None: iterctrl = lambda measure, i: True for i, measure in enumerate(iterate(expr).by_class(scoretools.Measure)): if iterctrl(measure, i): time_signature = measure.time_signature denominator = mathtools.greatest_power_of_two_less_equal( time_signature.denominator) numerator = time_signature.numerator notes = scoretools.Note(0, (1, denominator)) * numerator measure[:] = notes
def fill_measures_in_expr_with_time_signature_denominator_notes( expr, iterctrl=None): r'''Fill measures in `expr` with time signature denominator notes: :: >>> staff = Staff([Measure((3, 4), []), Measure((3, 16), []), Measure((3, 8), [])]) >>> scoretools.fill_measures_in_expr_with_time_signature_denominator_notes(staff) .. doctest:: >>> print(format(staff)) \new Staff { { \time 3/4 c'4 c'4 c'4 } { \time 3/16 c'16 c'16 c'16 } { \time 3/8 c'8 c'8 c'8 } } Delete existing contents of measures in `expr`. Returns none. ''' from abjad.tools import scoretools if iterctrl is None: iterctrl = lambda measure, i: True for i, measure in enumerate(iterate(expr).by_class(scoretools.Measure)): if iterctrl(measure, i): time_signature = measure.time_signature denominator = mathtools.greatest_power_of_two_less_equal( time_signature.denominator) numerator = time_signature.numerator notes = scoretools.Note(0, (1, denominator)) * numerator measure[:] = notes
def equal_or_greater_assignable(self): r'''Gets assignable duration equal to or just greater than this duration. .. container:: example **Example.** Gets equal-or-greater assignable duration: :: >>> for numerator in range(1, 16 + 1): ... duration = Duration(numerator, 16) ... result = duration.equal_or_greater_assignable ... sixteenths = duration.with_denominator(16) ... print('{!s}\t{!s}'.format(sixteenths, result)) ... 1/16 1/16 2/16 1/8 3/16 3/16 4/16 1/4 5/16 3/8 6/16 3/8 7/16 7/16 8/16 1/2 9/16 3/4 10/16 3/4 11/16 3/4 12/16 3/4 13/16 7/8 14/16 7/8 15/16 15/16 16/16 1 Returns new duration. ''' good_denominator = mathtools.greatest_power_of_two_less_equal( self.denominator) current_numerator = self.numerator candidate = type(self)(current_numerator, good_denominator) while not candidate.is_assignable: current_numerator += 1 candidate = type(self)(current_numerator, good_denominator) return candidate
def _get_likely_multiplier_of_components(components): pass from abjad.tools import scoretools from abjad.tools import selectiontools from abjad.tools import sequencetools assert all(isinstance(x, scoretools.Component) for x in components) logical_tie_duration_numerators = [] for expr in \ iterate(components).by_topmost_logical_ties_and_components(): if isinstance(expr, selectiontools.LogicalTie): logical_tie_duration = expr._preprolated_duration logical_tie_duration_numerators.append( logical_tie_duration.numerator) if len(sequencetools.remove_repeated_elements( logical_tie_duration_numerators)) == 1: numerator = logical_tie_duration_numerators[0] denominator = mathtools.greatest_power_of_two_less_equal(numerator) likely_multiplier = durationtools.Multiplier( numerator, denominator) return likely_multiplier
def _get_likely_multiplier_of_components(components): pass from abjad.tools import scoretools from abjad.tools import iterationtools from abjad.tools import leaftools from abjad.tools import selectiontools from abjad.tools import sequencetools assert all(isinstance(x, scoretools.Component) for x in components) chain_duration_numerators = [] for expr in \ iterationtools.iterate_topmost_tie_chains_and_components_in_expr( components): if isinstance(expr, selectiontools.TieChain): chain_duration = expr._preprolated_duration chain_duration_numerators.append(chain_duration.numerator) if len(sequencetools.truncate_runs_in_sequence( chain_duration_numerators)) == 1: numerator = chain_duration_numerators[0] denominator = mathtools.greatest_power_of_two_less_equal(numerator) likely_multiplier = durationtools.Multiplier(numerator, denominator) return likely_multiplier
def equal_or_greater_assignable(self): r'''Equal or greater assignable: :: >>> for numerator in range(1, 16 + 1): ... duration = Duration(numerator, 16) ... result = duration.equal_or_greater_assignable ... print '{}\t{}'.format( ... duration.with_denominator(16), result) ... 1/16 1/16 2/16 1/8 3/16 3/16 4/16 1/4 5/16 3/8 6/16 3/8 7/16 7/16 8/16 1/2 9/16 3/4 10/16 3/4 11/16 3/4 12/16 3/4 13/16 7/8 14/16 7/8 15/16 15/16 16/16 1 Returns new duration. ''' good_denominator = mathtools.greatest_power_of_two_less_equal( self.denominator) current_numerator = self.numerator candidate = type(self)(current_numerator, good_denominator) while not candidate.is_assignable: current_numerator += 1 candidate = type(self)(current_numerator, good_denominator) return candidate
def test_mathtools_greatest_power_of_two_less_equal_03(): r'''Optional offset keyword allows for the next to greatest integer power of two, etc.''' assert mathtools.greatest_power_of_two_less_equal(1, 1) == 0.5 assert mathtools.greatest_power_of_two_less_equal(2, 1) == 1 assert mathtools.greatest_power_of_two_less_equal(3, 1) == 1 assert mathtools.greatest_power_of_two_less_equal(4, 1) == 2 assert mathtools.greatest_power_of_two_less_equal(5, 1) == 2 assert mathtools.greatest_power_of_two_less_equal(6, 1) == 2 assert mathtools.greatest_power_of_two_less_equal(7, 1) == 2 assert mathtools.greatest_power_of_two_less_equal(8, 1) == 4 assert mathtools.greatest_power_of_two_less_equal(9, 1) == 4 assert mathtools.greatest_power_of_two_less_equal(10, 1) == 4 assert mathtools.greatest_power_of_two_less_equal(11, 1) == 4 assert mathtools.greatest_power_of_two_less_equal(12, 1) == 4
def make_notes( pitches, durations, decrease_durations_monotonically=True, use_messiaen_style_ties=False, ): r'''Makes notes according to `pitches` and `durations`. .. container:: example **Example 1.** Cycles through `pitches` when the length of `pitches` is less than the length of `durations`: :: >>> notes = scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)]) >>> notes Selection(Note("c'16"), Note("c'8"), Note("c'8")) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'16 c'8 c'8 } .. container:: example **Example 2.** Cycles through `durations` when the length of `durations` is less than the length of `pitches`: :: >>> notes = scoretools.make_notes( ... [0, 2, 4, 5, 7], ... [(1, 16), (1, 8), (1, 8)], ... ) >>> notes Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8")) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'16 d'8 e'8 f'16 g'8 } .. container:: example **Example 3.** Creates ad hoc tuplets for nonassignable durations: :: >>> notes = scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)]) >>> notes Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8")) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'16 \tweak #'edge-height #'(0.7 . 0) \times 2/3 { c'8 } c'8 } .. container:: example **Example 4.** Set ``decrease_durations_monotonically=True`` to express tied values in decreasing duration: :: >>> notes = scoretools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=True, ... ) >>> notes Selection(Note("c'2."), Note("c'16")) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'2. ~ c'16 } .. container:: example **Example 5.** Set ``decrease_durations_monotonically=False`` to express tied values in increasing duration: :: >>> notes = scoretools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=False, ... ) >>> notes Selection(Note("c'16"), Note("c'2.")) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'16 ~ c'2. } .. container:: example **Example 6.** Uses Messiaen-style ties: :: >>> notes = scoretools.make_notes( ... [0], ... [(13, 16)], ... use_messiaen_style_ties=True, ... ) >>> staff = Staff(notes) :: >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'2. c'16 \repeatTie } Set `pitches` to a single pitch or a sequence of pitches. Set `durations` to a single duration or a list of durations. Returns selection. ''' from abjad.tools import scoretools from abjad.tools import selectiontools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations] size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = sequencetools.repeat_sequence_to_length( nonreduced_fractions, size, ) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration durations = Duration._group_nonreduced_fractions_by_implied_prolation( nonreduced_fractions) def _make_unprolated_notes( pitches, durations, decrease_durations_monotonically=decrease_durations_monotonically, use_messiaen_style_ties=False, ): assert len(pitches) == len(durations) result = [] for pitch, duration in zip(pitches, durations): result.extend( scoretools.make_tied_leaf( scoretools.Note, duration, pitches=pitch, decrease_durations_monotonically=decrease_durations_monotonically, use_messiaen_style_ties=use_messiaen_style_ties, ) ) return result result = [] for duration in durations: # get factors in denominator of duration group duration not 1 or 2 factors = set(mathtools.factors(duration[0].denominator)) factors.discard(1) factors.discard(2) ps = pitches[0:len(duration)] pitches = pitches[len(duration):] if len(factors) == 0: result.extend( _make_unprolated_notes( ps, duration, decrease_durations_monotonically=decrease_durations_monotonically, use_messiaen_style_ties=use_messiaen_style_ties, ) ) else: # compute prolation denominator = duration[0].denominator numerator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / fractions.Fraction(*multiplier) duration = [ratio * durationtools.Duration(d) for d in duration] ns = _make_unprolated_notes( ps, duration, decrease_durations_monotonically=decrease_durations_monotonically, use_messiaen_style_ties=use_messiaen_style_ties, ) t = scoretools.Tuplet(multiplier, ns) result.append(t) # return result result = selectiontools.Selection(result) return result
def make_notes(pitches, durations, decrease_durations_monotonically=True): r'''Make notes according to `pitches` and `durations`. Cycle through `pitches` when the length of `pitches` is less than the length of `durations`: :: >>> scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)]) Selection(Note("c'16"), Note("c'8"), Note("c'8")) Cycle through `durations` when the length of `durations` is less than the length of `pitches`: :: >>> scoretools.make_notes([0, 2, 4, 5, 7], [(1, 16), (1, 8), (1, 8)]) Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8")) Create ad hoc tuplets for nonassignable durations: :: >>> scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)]) Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8")) Set ``decrease_durations_monotonically=True`` to express tied values in decreasing duration: :: >>> scoretools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=True, ... ) Selection(Note("c'2."), Note("c'16")) Set ``decrease_durations_monotonically=False`` to express tied values in increasing duration: :: >>> scoretools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=False, ... ) Selection(Note("c'16"), Note("c'2.")) Set `pitches` to a single pitch or a sequence of pitches. Set `durations` to a single duration or a list of durations. Returns selection. ''' from abjad.tools import scoretools from abjad.tools import selectiontools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations] size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = sequencetools.repeat_sequence_to_length( nonreduced_fractions, size, ) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration durations = Duration._group_nonreduced_fractions_by_implied_prolation( nonreduced_fractions) def _make_unprolated_notes( pitches, durations, decrease_durations_monotonically=decrease_durations_monotonically, ): assert len(pitches) == len(durations) result = [] for pitch, duration in zip(pitches, durations): result.extend( scoretools.make_tied_leaf( scoretools.Note, duration, pitches=pitch, decrease_durations_monotonically= decrease_durations_monotonically, )) return result result = [] for duration in durations: # get factors in denominator of duration group duration other than 1, 2. factors = set(mathtools.factors(duration[0].denominator)) factors.discard(1) factors.discard(2) ps = pitches[0:len(duration)] pitches = pitches[len(duration):] if len(factors) == 0: result.extend( _make_unprolated_notes(ps, duration, decrease_durations_monotonically= decrease_durations_monotonically)) else: # compute prolation denominator = duration[0].denominator numerator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / fractions.Fraction(*multiplier) duration = [ratio * durationtools.Duration(d) for d in duration] ns = _make_unprolated_notes(ps, duration, decrease_durations_monotonically= decrease_durations_monotonically) t = scoretools.Tuplet(multiplier, ns) result.append(t) # return result result = selectiontools.Selection(result) return result
def make_leaves( pitches, durations, decrease_durations_monotonically=True, tie_rests=False, forbidden_written_duration=None, metrical_hiearchy=None, ): r'''Make leaves. .. container:: example **Example 1.** Integer and string elements in `pitches` result in notes: :: >>> pitches = [2, 4, 'F#5', 'G#5'] >>> duration = Duration(1, 4) >>> leaves = leaftools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { d'4 e'4 fs''4 gs''4 } .. container:: example **Example 2.** Tuple elements in `pitches` result in chords: :: >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')] >>> duration = Duration(1, 2) >>> leaves = leaftools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { <c' d' e'>2 <fs'' gs'' as''>2 } .. container:: example **Example 3.** None-valued elements in `pitches` result in rests: :: >>> pitches = 4 * [None] >>> durations = [Duration(1, 4)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = stafftools.RhythmicStaff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new RhythmicStaff { r4 r4 r4 r4 } .. container:: example **Example 4.** You can mix and match values passed to `pitches`: :: >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5'] >>> durations = [Duration(1, 4)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { <c' d' e'>4 r4 cs''4 ds''4 } .. container:: example **Example 5.** Read `pitches` cyclically when the length of `pitches` is less than the length of `durations`: :: >>> pitches = ['C5'] >>> durations = 2 * [Duration(3, 8), Duration(1, 8)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { c''4. c''8 c''4. c''8 } .. container:: example **Example 6.** Read `durations` cyclically when the length of `durations` is less than the length of `pitches`: :: >>> pitches = "c'' d'' e'' f''" >>> durations = [Duration(1, 4)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { c''4 d''4 e''4 f''4 } .. container:: example **Example 7.** Elements in `durations` with non-power-of-two denominators result in tuplet-nested leaves: :: >>> pitches = ['D5'] >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \times 2/3 { d''2 d''2 d''2 } } .. container:: example **Example 8.** Set `decrease_durations_monotonically` to true to return nonassignable durations tied from greatest to least: :: >>> pitches = ['D#5'] >>> durations = [Duration(13, 16)] >>> leaves = leaftools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> time_signature = contexttools.TimeSignatureMark((13, 16)) >>> time_signature = attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 13/16 ds''2. ~ ds''16 } .. container:: example **Example 9.** Set `decrease_durations_monotonically` to false to return nonassignable durations tied from least to greatest: :: >>> pitches = ['E5'] >>> durations = [Duration(13, 16)] >>> leaves = leaftools.make_leaves( ... pitches, ... durations, ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = contexttools.TimeSignatureMark((13, 16)) >>> time_signature = attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 13/16 e''16 ~ e''2. } .. container:: example **Example 10.** Set `tie_rests` to true to return tied rests for nonassignable durations. Note that LilyPond does not engrave ties between rests: :: >>> pitches = [None] >>> durations = [Duration(5, 8)] >>> leaves = leaftools.make_leaves( ... pitches, ... durations, ... tie_rests=True, ... ) >>> staff = stafftools.RhythmicStaff(leaves) >>> time_signature = contexttools.TimeSignatureMark((5, 8)) >>> time_signature = attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new RhythmicStaff { \time 5/8 r2 ~ r8 } .. container:: example **Example 11.** Set `forbidden_written_duration` to avoid notes greater than or equal to a certain written duration: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = leaftools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... ) >>> staff = Staff(leaves) >>> time_signature = contexttools.TimeSignatureMark((5, 4)) >>> time_signature = attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 f'4 ~ f'4 ~ f'8 g'4 ~ g'4 ~ g'8 } .. container:: example **Example 12.** You may set `forbidden_written_duration` and `decrease_durations_monotonically` together: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = leaftools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = contexttools.TimeSignatureMark((5, 4)) >>> time_siganture = attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 f'8 ~ f'4 ~ f'4 g'8 ~ g'4 ~ g'4 } Returns selection of unincorporated leaves. ''' from abjad.tools import scoretools from abjad.tools import notetools from abjad.tools import resttools from abjad.tools import tuplettools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] # make duration pairs duration_pairs = [durationtools.Duration(duration) for duration in durations] # set lists of pitches and duration pairs to the same length size = max(len(duration_pairs), len(pitches)) duration_pairs = \ sequencetools.repeat_sequence_to_length(duration_pairs, size) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration duration_groups = \ Duration._group_nonreduced_fractions_by_implied_prolation( duration_pairs) result = [] for duration_group in duration_groups: # get factors in denominator of duration group other than 1, 2. factors = set(mathtools.factors(duration_group[0].denominator)) factors.discard(1) factors.discard(2) current_pitches = pitches[0:len(duration_group)] pitches = pitches[len(duration_group):] if len(factors) == 0: for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically=decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, tie_rests=tie_rests, ) result.extend(leaves) else: # compute tuplet prolation denominator = duration_group[0].denominator numerator = \ mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / durationtools.Duration(*multiplier) duration_group = [ratio * durationtools.Duration(duration) for duration in duration_group] # make tuplet leaves tuplet_leaves = [] for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically=decrease_durations_monotonically, ) tuplet_leaves.extend(leaves) tuplet = tuplettools.Tuplet(multiplier, tuplet_leaves) result.append(tuplet) result = selectiontools.Selection(result) return result
def make_notes(pitches, durations, decrease_durations_monotonically=True): r'''Make notes according to `pitches` and `durations`. Cycle through `pitches` when the length of `pitches` is less than the length of `durations`: :: >>> notetools.make_notes([0], [(1, 16), (1, 8), (1, 8)]) Selection(Note("c'16"), Note("c'8"), Note("c'8")) Cycle through `durations` when the length of `durations` is less than the length of `pitches`: :: >>> notetools.make_notes([0, 2, 4, 5, 7], [(1, 16), (1, 8), (1, 8)]) Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8")) Create ad hoc tuplets for nonassignable durations: :: >>> notetools.make_notes([0], [(1, 16), (1, 12), (1, 8)]) Selection(Note("c'16"), Tuplet(2/3, [c'8]), Note("c'8")) Set ``decrease_durations_monotonically=True`` to express tied values in decreasing duration: :: >>> notetools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=True, ... ) Selection(Note("c'2."), Note("c'16")) Set ``decrease_durations_monotonically=False`` to express tied values in increasing duration: :: >>> notetools.make_notes( ... [0], ... [(13, 16)], ... decrease_durations_monotonically=False, ... ) Selection(Note("c'16"), Note("c'2.")) Set `pitches` to a single pitch or a sequence of pitches. Set `durations` to a single duration or a list of durations. Returns list of newly constructed notes. ''' from abjad.tools import leaftools from abjad.tools import notetools from abjad.tools import selectiontools from abjad.tools import tuplettools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] duration_pairs = [durationtools.Duration(duration) for duration in durations] # set lists of pitches and duration pairs to the same length size = max(len(duration_pairs), len(pitches)) duration_pairs = \ sequencetools.repeat_sequence_to_length(duration_pairs, size) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration durations = Duration._group_nonreduced_fractions_by_implied_prolation( duration_pairs) def _make_unprolated_notes( pitches, durations, decrease_durations_monotonically=decrease_durations_monotonically, ): assert len(pitches) == len(durations) result = [] for pitch, duration in zip(pitches, durations): result.extend(leaftools.make_tied_leaf( notetools.Note, duration, pitches=pitch, decrease_durations_monotonically=decrease_durations_monotonically, )) return result result = [] for duration in durations: # get factors in denominator of duration group duration other than 1, 2. factors = set(mathtools.factors(duration[0].denominator)) factors.discard(1) factors.discard(2) ps = pitches[0:len(duration)] pitches = pitches[len(duration):] if len(factors) == 0: result.extend(_make_unprolated_notes(ps, duration, decrease_durations_monotonically=decrease_durations_monotonically)) else: # compute prolation denominator = duration[0].denominator numerator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / fractions.Fraction(*multiplier) duration = [ratio * durationtools.Duration(d) for d in duration] ns = _make_unprolated_notes(ps, duration, decrease_durations_monotonically=decrease_durations_monotonically) t = tuplettools.Tuplet(multiplier, ns) result.append(t) # return result result = selectiontools.Selection(result) return result
def make_leaves( pitches, durations, decrease_durations_monotonically=True, forbidden_written_duration=None, is_diminution=True, metrical_hiearchy=None, use_messiaen_style_ties=False, use_multimeasure_rests=False, ): r'''Makes leaves. .. container:: example **Example 1.** Integer and string elements in `pitches` result in notes: :: >>> pitches = [2, 4, 'F#5', 'G#5'] >>> duration = Duration(1, 4) >>> leaves = scoretools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { d'4 e'4 fs''4 gs''4 } .. container:: example **Example 2.** Tuple elements in `pitches` result in chords: :: >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')] >>> duration = Duration(1, 2) >>> leaves = scoretools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { <c' d' e'>2 <fs'' gs'' as''>2 } .. container:: example **Example 3.** None-valued elements in `pitches` result in rests: :: >>> pitches = 4 * [None] >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new RhythmicStaff { r4 r4 r4 r4 } .. container:: example **Example 4.** You can mix and match values passed to `pitches`: :: >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5'] >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { <c' d' e'>4 r4 cs''4 ds''4 } .. container:: example **Example 5.** Read `pitches` cyclically when the length of `pitches` is less than the length of `durations`: :: >>> pitches = ['C5'] >>> durations = 2 * [Duration(3, 8), Duration(1, 8)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { c''4. c''8 c''4. c''8 } .. container:: example **Example 6.** Read `durations` cyclically when the length of `durations` is less than the length of `pitches`: :: >>> pitches = "c'' d'' e'' f''" >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { c''4 d''4 e''4 f''4 } .. container:: example **Example 7.** Elements in `durations` with non-power-of-two denominators result in tuplet-nested leaves: :: >>> pitches = ['D5'] >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \times 2/3 { d''2 d''2 d''2 } } .. container:: example **Example 8.** Set `decrease_durations_monotonically` to true to return nonassignable durations tied from greatest to least: :: >>> pitches = ['D#5'] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((13, 16)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 13/16 ds''2. ~ ds''16 } .. container:: example **Example 9.** Set `decrease_durations_monotonically` to false to return nonassignable durations tied from least to greatest: :: >>> pitches = ['E5'] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((13, 16)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 13/16 e''16 ~ e''2. } .. container:: example **Example 10.** Set `forbidden_written_duration` to avoid notes greater than or equal to a certain written duration: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 f'4 ~ f'4 ~ f'8 g'4 ~ g'4 ~ g'8 } .. container:: example **Example 11.** You may set `forbidden_written_duration` and `decrease_durations_monotonically` together: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 f'8 ~ f'4 ~ f'4 g'8 ~ g'4 ~ g'4 } .. container:: example **Example 12.** Set `is_diminution` to true to produce diminished tuplets: :: >>> pitches = "f'" >>> durations = [Duration(5, 14)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... is_diminution=True ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 14)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/14 \tweak edge-height #'(0.7 . 0) \times 4/7 { f'2 ~ f'8 } } This is default behavior. .. container:: example **Example 13.** Set `is_diminution` to false to produce agumented tuplets: :: >>> pitches = "f'" >>> durations = [Duration(5, 14)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... is_diminution=False ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 14)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/14 \tweak text #tuplet-number::calc-fraction-text \tweak edge-height #'(0.7 . 0) \times 8/7 { f'4 ~ f'16 } } .. container:: example **Example 14.** None-valued elements in `pitches` result in multimeasure rests when the multimeasure rest keyword is set: :: >>> pitches = [None] >>> durations = [Duration(3, 8), Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... use_multimeasure_rests=True, ... ) >>> leaves Selection(MultimeasureRest('R1 * 3/8'), MultimeasureRest('R1 * 5/8')) :: >>> staff = Staff([ ... Measure((3, 8), [leaves[0]]), ... Measure((5, 8), [leaves[1]]), ... ]) >>> staff.context_name = 'RhythmicStaff' >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new RhythmicStaff { { \time 3/8 R1 * 3/8 } { \time 5/8 R1 * 5/8 } } .. container:: example **Example 15.** Uses Messiaen-style ties: :: >>> pitches = [0] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... use_messiaen_style_ties=True, ... ) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { c'2. c'16 \repeatTie } .. container:: example **Example 16.** Works with numbered pitch-class: :: >>> pitches = [pitchtools.NumberedPitchClass(6)] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... ) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { fs'2. ~ fs'16 } Returns selection of leaves. ''' from abjad.tools import scoretools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations] size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = sequencetools.repeat_sequence_to_length( nonreduced_fractions, size, ) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration duration_groups = \ Duration._group_nonreduced_fractions_by_implied_prolation( nonreduced_fractions) result = [] for duration_group in duration_groups: # get factors in denominator of duration group other than 1, 2. factors = set(mathtools.factors(duration_group[0].denominator)) factors.discard(1) factors.discard(2) current_pitches = pitches[0:len(duration_group)] pitches = pitches[len(duration_group):] if len(factors) == 0: for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically=decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_multimeasure_rests=use_multimeasure_rests, use_messiaen_style_ties=use_messiaen_style_ties, ) result.extend(leaves) else: # compute tuplet prolation denominator = duration_group[0].denominator numerator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / durationtools.Duration(*multiplier) duration_group = [ratio * durationtools.Duration(duration) for duration in duration_group] # make tuplet leaves tuplet_leaves = [] for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically=\ decrease_durations_monotonically, use_multimeasure_rests=use_multimeasure_rests, use_messiaen_style_ties=use_messiaen_style_ties, ) tuplet_leaves.extend(leaves) tuplet = scoretools.Tuplet(multiplier, tuplet_leaves) if is_diminution and not tuplet.is_diminution: tuplet.toggle_prolation() elif not is_diminution and tuplet.is_diminution: tuplet.toggle_prolation() result.append(tuplet) result = selectiontools.Selection(result) return result
# -*- encoding: utf-8 -*- import fractions from abjad.tools import mathtools denominators = range(4, 15 + 1) + range(16, 30 + 1, 2) multipliers = set([]) for denominator in denominators: base_denominator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = fractions.Fraction(base_denominator, denominator) ratio = '%s:%s' % (multiplier.denominator, multiplier.numerator) #print ratio, '\t', multiplier * Fraction(1, base_denominator) multipliers.add(multiplier) sargasso_multipliers = tuple(sorted(multipliers)) output_preamble_lines = ['from fractions import Fraction\n']
def test_mathtools_greatest_power_of_two_less_equal_01(): r'''Returns greatest integer power of two less than or equal to n.''' assert mathtools.greatest_power_of_two_less_equal(1) == 1 assert mathtools.greatest_power_of_two_less_equal(2) == 2 assert mathtools.greatest_power_of_two_less_equal(3) == 2 assert mathtools.greatest_power_of_two_less_equal(4) == 4 assert mathtools.greatest_power_of_two_less_equal(5) == 4 assert mathtools.greatest_power_of_two_less_equal(6) == 4 assert mathtools.greatest_power_of_two_less_equal(7) == 4 assert mathtools.greatest_power_of_two_less_equal(8) == 8 assert mathtools.greatest_power_of_two_less_equal(9) == 8 assert mathtools.greatest_power_of_two_less_equal(10) == 8 assert mathtools.greatest_power_of_two_less_equal(11) == 8 assert mathtools.greatest_power_of_two_less_equal(12) == 8
def make_leaves( pitches, durations, decrease_durations_monotonically=True, forbidden_written_duration=None, is_diminution=True, metrical_hiearchy=None, use_messiaen_style_ties=False, use_multimeasure_rests=False, ): r'''Makes leaves. .. container:: example **Example 1.** Integer and string elements in `pitches` result in notes: :: >>> pitches = [2, 4, 'F#5', 'G#5'] >>> duration = Duration(1, 4) >>> leaves = scoretools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { d'4 e'4 fs''4 gs''4 } .. container:: example **Example 2.** Tuple elements in `pitches` result in chords: :: >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')] >>> duration = Duration(1, 2) >>> leaves = scoretools.make_leaves(pitches, duration) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { <c' d' e'>2 <fs'' gs'' as''>2 } .. container:: example **Example 3.** None-valued elements in `pitches` result in rests: :: >>> pitches = 4 * [None] >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { r4 r4 r4 r4 } .. container:: example **Example 4.** You can mix and match values passed to `pitches`: :: >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5'] >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { <c' d' e'>4 r4 cs''4 ds''4 } .. container:: example **Example 5.** Read `pitches` cyclically when the length of `pitches` is less than the length of `durations`: :: >>> pitches = ['C5'] >>> durations = 2 * [Duration(3, 8), Duration(1, 8)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c''4. c''8 c''4. c''8 } .. container:: example **Example 6.** Read `durations` cyclically when the length of `durations` is less than the length of `pitches`: :: >>> pitches = "c'' d'' e'' f''" >>> durations = [Duration(1, 4)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c''4 d''4 e''4 f''4 } .. container:: example **Example 7.** Elements in `durations` with non-power-of-two denominators result in tuplet-nested leaves: :: >>> pitches = ['D5'] >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \times 2/3 { d''2 d''2 d''2 } } .. container:: example **Example 8.** Set `decrease_durations_monotonically` to true to return nonassignable durations tied from greatest to least: :: >>> pitches = ['D#5'] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves(pitches, durations) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((13, 16)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 13/16 ds''2. ~ ds''16 } .. container:: example **Example 9.** Set `decrease_durations_monotonically` to false to return nonassignable durations tied from least to greatest: :: >>> pitches = ['E5'] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((13, 16)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 13/16 e''16 ~ e''2. } .. container:: example **Example 10.** Set `forbidden_written_duration` to avoid notes greater than or equal to a certain written duration: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 5/4 f'4 ~ f'4 ~ f'8 g'4 ~ g'4 ~ g'8 } .. container:: example **Example 11.** You may set `forbidden_written_duration` and `decrease_durations_monotonically` together: :: >>> pitches = "f' g'" >>> durations = [Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... forbidden_written_duration=Duration(1, 2), ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 5/4 f'8 ~ f'4 ~ f'4 g'8 ~ g'4 ~ g'4 } .. container:: example **Example 12.** Set `is_diminution` to true to produce diminished tuplets: :: >>> pitches = "f'" >>> durations = [Duration(5, 14)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... is_diminution=True ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 14)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 5/14 \tweak #'edge-height #'(0.7 . 0) \times 4/7 { f'2 ~ f'8 } } This is default behavior. .. container:: example **Example 13.** Set `is_diminution` to false to produce agumented tuplets: :: >>> pitches = "f'" >>> durations = [Duration(5, 14)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... is_diminution=False ... ) >>> staff = Staff(leaves) >>> time_signature = TimeSignature((5, 14)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \time 5/14 \tweak #'text #tuplet-number::calc-fraction-text \tweak #'edge-height #'(0.7 . 0) \times 8/7 { f'4 ~ f'16 } } .. container:: example **Example 14.** None-valued elements in `pitches` result in multimeasure rests when the multimeasure rest keyword is set: :: >>> pitches = [None] >>> durations = [Duration(3, 8), Duration(5, 8)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... use_multimeasure_rests=True, ... ) >>> leaves Selection(MultimeasureRest('R1 * 3/8'), MultimeasureRest('R1 * 5/8')) :: >>> staff = Staff([ ... Measure((3, 8), [leaves[0]]), ... Measure((5, 8), [leaves[1]]), ... ]) >>> staff.context_name = 'RhythmicStaff' >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { { \time 3/8 R1 * 3/8 } { \time 5/8 R1 * 5/8 } } .. container:: example **Example 15.** Uses Messiaen-style ties: :: >>> pitches = [0] >>> durations = [Duration(13, 16)] >>> leaves = scoretools.make_leaves( ... pitches, ... durations, ... use_messiaen_style_ties=True, ... ) >>> staff = Staff(leaves) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { c'2. c'16 \repeatTie } Returns selection of leaves. ''' from abjad.tools import scoretools if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, list): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations] size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = sequencetools.repeat_sequence_to_length( nonreduced_fractions, size, ) pitches = sequencetools.repeat_sequence_to_length(pitches, size) Duration = durationtools.Duration duration_groups = \ Duration._group_nonreduced_fractions_by_implied_prolation( nonreduced_fractions) result = [] for duration_group in duration_groups: # get factors in denominator of duration group other than 1, 2. factors = set(mathtools.factors(duration_group[0].denominator)) factors.discard(1) factors.discard(2) current_pitches = pitches[0:len(duration_group)] pitches = pitches[len(duration_group):] if len(factors) == 0: for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically= decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_multimeasure_rests=use_multimeasure_rests, use_messiaen_style_ties=use_messiaen_style_ties, ) result.extend(leaves) else: # compute tuplet prolation denominator = duration_group[0].denominator numerator = mathtools.greatest_power_of_two_less_equal(denominator) multiplier = (numerator, denominator) ratio = 1 / durationtools.Duration(*multiplier) duration_group = [ ratio * durationtools.Duration(duration) for duration in duration_group ] # make tuplet leaves tuplet_leaves = [] for pitch, duration in zip(current_pitches, duration_group): leaves = _make_leaf_on_pitch( pitch, duration, decrease_durations_monotonically=\ decrease_durations_monotonically, use_multimeasure_rests=use_multimeasure_rests, use_messiaen_style_ties=use_messiaen_style_ties, ) tuplet_leaves.extend(leaves) tuplet = scoretools.Tuplet(multiplier, tuplet_leaves) if is_diminution and not tuplet.is_diminution: tuplet.toggle_prolation() elif not is_diminution and tuplet.is_diminution: tuplet.toggle_prolation() result.append(tuplet) result = selectiontools.Selection(result) return result