def _update_all_leaf_indices_and_measure_numbers(component): r'''Call only when updating offsets. No separate state flags exist for leaf indices or measure numbers. ''' from abjad.tools import scoretools from abjad.tools.topleveltools import iterate parentage = component._get_parentage() score_root = parentage.root if isinstance(score_root, scoretools.Context): contexts = iterate(score_root).by_class(scoretools.Context) for context in contexts: for leaf_index, leaf in enumerate( iterate(context).by_class(scoretools.Leaf)): leaf._leaf_index = leaf_index for measure_index, measure in enumerate( iterate(context).by_class(scoretools.Measure)): measure_number = measure_index + 1 measure._measure_number = measure_number else: for leaf_index, leaf in enumerate( iterate(score_root).by_class(scoretools.Leaf)): leaf._leaf_index = leaf_index for measure_index, measure in enumerate( iterate(score_root).by_class(scoretools.Measure)): measure_number = measure_index + 1 measure._measure_number = measure_number
def toggle_prolation(self): r'''Toggles prolation of fixed-duration tuplet. :: >>> tuplet = scoretools.FixedDurationTuplet((1, 4), "c'8 d'8 e'8") >>> show(tuplet) # doctest: +SKIP :: >>> tuplet.toggle_prolation() >>> show(tuplet) # doctest: +SKIP :: >>> tuplet.toggle_prolation() >>> show(tuplet) # doctest: +SKIP Returns none. ''' if self.is_diminution: while self.is_diminution: for leaf in iterate(self).by_leaf(): leaf.written_duration /= 2 elif not self.is_diminution: while not self.is_diminution: for leaf in iterate(self).by_leaf(): leaf.written_duration *= 2
def _make_music(self, duration_pairs, seeds): from abjad.tools import rhythmmakertools selections = [] specifier = self.duration_spelling_specifier if specifier is None: specifier = rhythmmakertools.DurationSpellingSpecifier() for duration_pair in duration_pairs: selection = scoretools.make_leaves( pitches=0, durations=[duration_pair], decrease_durations_monotonically=\ specifier.decrease_durations_monotonically, forbidden_written_duration=\ specifier.forbidden_written_duration, ) selections.append(selection) beam_specifier = self.beam_specifier if beam_specifier is None: beam_specifier = rhythmmakertools.BeamSpecifier() if beam_specifier.beam_divisions_together: for component in iterate(selections).by_class(): detach(spannertools.Beam, component) beam = spannertools.MultipartBeam() leaves = iterate(selections).by_class(scoretools.Leaf) leaves = list(leaves) attach(beam, leaves) elif beam_specifier.beam_each_division: for selection in selections: beam = spannertools.MultipartBeam() attach(beam, selection) return selections
def apply_spanners(self, score): spanner_groups = { # 'groups': lambda score: groupby( # score, # key=lambda x: get_named_annotation(x, 'groups'), # eqcheck=contains_any, # ), 'notation': group_events( lambda x: get_named_annotation(x, 'notation'), ), 'instrument': group_events( lambda x: ( get_named_annotation(x, 'part'), get_named_annotation(x, 'instrument'), ) ), } # groups classes = (scoretools.Chord, scoretools.Rest) chords_iterator = list(topleveltools.iterate(score).by_class(classes)) tie_groups = get_tie_groups(list(chords_iterator)) for tie_group in tie_groups: if isinstance(tie_group[0], scoretools.Chord): spanner = NotationSpanner(key='groups', value=True) topleveltools.attach(spanner, tie_group) # notation, instrument for spanner_name, group_fn in spanner_groups.items(): classes = (scoretools.Chord, scoretools.Rest) chords_iterator = topleveltools.iterate(score).by_class(classes) for k, g in group_fn(chords_iterator): group = list(g) if k and isinstance(group[0], scoretools.Chord): spanner = NotationSpanner(key=spanner_name, value=k) topleveltools.attach(spanner, group)
def __call__(self, expr, offset=0): leaves = list(iterate(expr).by_class(scoretools.Leaf)) groups = list(iterate(leaves).by_run( (scoretools.Note, scoretools.Chord))) hairpin_tokens = datastructuretools.CyclicTuple(self.hairpin_tokens) for i, group in enumerate(groups): if not isinstance(group, selectiontools.SliceSelection): group = selectiontools.SliceSelection(group) is_short_group = False hairpin_token = hairpin_tokens[offset + i] if len(group) == 1: is_short_group = True elif self.minimum_duration is not None: if group.get_duration() < self.minimum_duration: is_short_group = True if is_short_group: start_dynamic = hairpin_token[0] #indicatortools.Dynamic(start_dynamic)(group[0]) command = indicatortools.LilyPondCommand(start_dynamic, 'right') attach(command, group[0]) else: descriptor = ' '.join([x for x in hairpin_token if x]) hairpin = spannertools.Hairpin( descriptor=descriptor, include_rests=False, ) attach(hairpin, group) return expr
def _beam_rhythm_containers(self, rhythm_containers): beam_specifier = self.source_expression.beam_specifier beam_specifier = beam_specifier or rhythmmakertools.BeamSpecifier() beam_divisions_together = beam_specifier.beam_divisions_together beam_each_division = beam_specifier.beam_each_division if beam_divisions_together: for container in iterate(rhythm_containers).by_class(): spanners = container._get_spanners(spannertools.Beam) for spanner in spanners: spanner._sever_all_components() durations = [x._get_duration() for x in rhythm_containers] beam = spannertools.DuratedComplexBeam( durations=durations, span_beam_count=1, ) attach(beam, rhythm_containers) elif beam_each_division: for container in iterate(rhythm_containers).by_class(): spanners = container._get_spanners(spannertools.Beam) for spanner in spanners: spanner._sever_all_components() for rhythm_container in rhythm_containers: duration = rhythm_container._get_duration() beam = spannertools.DuratedComplexBeam( durations=[duration], span_beam_count=1, ) attach(beam, rhythm_container)
def build_leaf_offset_lists(self): for voice in iterate(self.score).by_class(scoretools.Voice): voice_proxy = \ self.score_specification.voice_data_structures_by_voice[ voice.name] for leaf in iterate(voice).by_class(scoretools.Leaf): voice_proxy.leaf_start_offsets.append( leaf._get_timespan().start_offset) voice_proxy.leaf_stop_offsets.append( leaf._get_timespan().stop_offset) voice_proxy.leaves.append(leaf)
def _make_ties_across_divisions(self, music): if not self.tie_across_divisions: return if self.tie_across_divisions == True: for division_one, division_two in \ sequencetools.iterate_sequence_nwise(music): leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True)) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf)) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) elif isinstance(self.tie_across_divisions, (tuple, list)): tie_across_divisions = datastructuretools.CyclicTuple( self.tie_across_divisions ) pairs = sequencetools.iterate_sequence_nwise(music) for i, pair in enumerate(pairs): indicator = tie_across_divisions[i] if not bool(indicator): continue division_one, division_two = pair leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) else: raise TypeError(self.tie_across_divisions)
def label_leaves_in_expr_with_numbered_interval_classes( expr, markup_direction=Up): r"""Label leaves in `expr` with numbered interval classes: :: >>> notes = scoretools.make_notes( ... [0, 25, 11, -4, -14, -13, 9, 10, 6, 5], ... [Duration(1, 8)], ... ) >>> staff = Staff(notes) >>> labeltools.label_leaves_in_expr_with_numbered_interval_classes( ... staff) .. doctest:: >>> print(format(staff)) \new Staff { c'8 ^ \markup { +1 } cs'''8 ^ \markup { -2 } b'8 ^ \markup { -3 } af8 ^ \markup { -10 } bf,8 ^ \markup { +1 } b,8 ^ \markup { +10 } a'8 ^ \markup { +1 } bf'8 ^ \markup { -4 } fs'8 ^ \markup { -1 } f'8 } :: >>> show(staff) # doctest: +SKIP Returns none. """ for note in iterate(expr).by_class(scoretools.Note): logical_voice_iterator = iterate(note).by_logical_voice_from_component( scoretools.Leaf, ) try: next(logical_voice_iterator) next_leaf = next(logical_voice_iterator) if isinstance(next_leaf, scoretools.Note): mdi = note.written_pitch - next_leaf.written_pitch mci = pitchtools.NumberedInterval(mdi) mcic = pitchtools.NumberedIntervalClass(mci) markup = markuptools.Markup(mcic, markup_direction) attach(markup, note) except StopIteration: pass
def _do_tie_across_divisions(self, divisions): from abjad.tools import rhythmmakertools if not self.tie_across_divisions: return if self.strip_ties: return if self.tie_consecutive_notes: return length = len(divisions) tie_across_divisions = self.tie_across_divisions if isinstance(tie_across_divisions, bool): tie_across_divisions = [tie_across_divisions] if not isinstance(tie_across_divisions, patterntools.Pattern): tie_across_divisions = patterntools.Pattern.from_vector( tie_across_divisions) pairs = sequencetools.iterate_sequence_nwise(divisions) rest_prototype = (scoretools.Rest, scoretools.MultimeasureRest) for i, pair in enumerate(pairs): if not tie_across_divisions.matches_index(i, length): continue division_one, division_two = pair leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] if isinstance(leaf_one, rest_prototype): continue if isinstance(leaf_two, rest_prototype): continue prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two tie_spanner = spannertools.Tie( use_messiaen_style_ties=self.use_messiaen_style_ties, ) tie_spanner._unconstrain_contiguity() attach(tie_spanner, combined_logical_tie) tie_spanner._constrain_contiguity()
def label_leaves_in_expr_with_numbered_intervals(expr, markup_direction=Up): r"""Label leaves in `expr` with numbered intervals: :: >>> notes = scoretools.make_notes( ... [0, 25, 11, -4, -14, -13, 9, 10, 6, 5], ... [Duration(1, 8)], ... ) >>> staff = Staff(notes) >>> labeltools.label_leaves_in_expr_with_numbered_intervals(staff) .. doctest:: >>> print format(staff) \new Staff { c'8 ^ \markup { +25 } cs'''8 ^ \markup { -14 } b'8 ^ \markup { -15 } af8 ^ \markup { -10 } bf,8 ^ \markup { +1 } b,8 ^ \markup { +22 } a'8 ^ \markup { +1 } bf'8 ^ \markup { -4 } fs'8 ^ \markup { -1 } f'8 } :: >>> show(staff) # doctest: +SKIP Returns none. """ for note in iterate(expr).by_class(scoretools.Note): logical_voice_iterator = iterate(note).by_logical_voice_from_component( scoretools.Leaf, ) try: logical_voice_iterator.next() next_leaf = logical_voice_iterator.next() if isinstance(next_leaf, scoretools.Note): mci = pitchtools.NumberedInterval.from_pitch_carriers( note, next_leaf) markup = markuptools.Markup(mci, markup_direction) attach(markup, note) except StopIteration: pass
def are_scalar_notes(self): r'''Is true when notes in selection are scalar. :: >>> selection_1.are_scalar_notes() True Otherwise false: :: >>> selection_2.are_scalar_notes() False Returns true or false. ''' from abjad.tools import scoretools direction_string = None for left, right in sequencetools.iterate_sequence_nwise( iterate(self._client).by_class(scoretools.Note)): try: assert not (left.written_pitch == right.written_pitch) mdi = pitchtools.NamedInterval.from_pitch_carriers( left, right) assert mdi.number <= 2 if direction_string is None: direction_string = mdi.direction_string assert direction_string == mdi.direction_string except AssertionError: return False return True
def label_leaves_in_expr_with_pitch_numbers(expr, markup_direction=Down): r'''Label leaves in `expr` with pitch numbers: :: >>> staff = Staff(scoretools.make_leaves([None, 12, [13, 14, 15], None], [(1, 4)])) >>> labeltools.label_leaves_in_expr_with_pitch_numbers(staff) >>> print(format(staff)) \new Staff { r4 c''4 _ \markup { \small 12 } <cs'' d'' ef''>4 _ \markup { \column { \small 15 \small 14 \small 13 } } r4 } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for leaf in iterate(expr).by_class(scoretools.Leaf): for pitch in reversed(pitchtools.PitchSegment.from_selection(leaf)): if pitch is not None: label = markuptools.MarkupCommand('small', str(pitch.pitch_number)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def __illustrate__(self): r'''Illustrates pitch segment. :: >>> named_pitch_segment = pitchtools.PitchSegment( ... ['bf,', 'aqs', "fs'", "g'", 'bqf', "g'"], ... item_class=NamedPitch, ... ) >>> show(named_pitch_segment) # doctest: +SKIP Returns LilyPond file. ''' from abjad.tools import durationtools from abjad.tools import lilypondfiletools from abjad.tools import markuptools from abjad.tools import pitchtools from abjad.tools import scoretools from abjad.tools.topleveltools import attach from abjad.tools.topleveltools import iterate from abjad.tools.topleveltools import override named_pitches = [pitchtools.NamedPitch(x) for x in self] notes = scoretools.make_notes(named_pitches, [1]) score, treble_staff, bass_staff = \ scoretools.make_piano_sketch_score_from_leaves(notes) for leaf in iterate(score).by_class(scoretools.Leaf): attach(durationtools.Multiplier(1, 8), leaf) override(score).rest.transparent = True lilypond_file = lilypondfiletools.make_basic_lilypond_file(score) lilypond_file.header_block.tagline = markuptools.Markup('""') return lilypond_file
def check_beamed_quarter_notes(self): r'''Checks to make sure there are no beamed quarter notes. Returns violators and total. ''' from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools.topleveltools import iterate violators = [] total = 0 smart_beams = ( spannertools.DuratedComplexBeam, spannertools.MultipartBeam, ) for leaf in iterate(self.expr).by_class(scoretools.Leaf): total += 1 parentage = leaf._get_parentage(include_self=True) beams = parentage._get_spanners(spannertools.Beam) for beam in beams: if not isinstance(beam, smart_beams): flag_count = leaf.written_duration.flag_count if flag_count < 1: violators.append(leaf) break return violators, total
def iterate_out_of_range_notes_and_chords(expr): '''Iterates notes and chords in `expr` outside traditional instrument ranges. .. todo:: Move to WellformednessManager. .. container:: example **Example.** Iterates out-of-range notes and chords: :: >>> staff = Staff("c'8 r8 <d fs>8 r8") >>> violin = instrumenttools.Violin() >>> attach(violin, staff) >>> show(staff) # doctest: +SKIP :: >>> list( ... instrumenttools.iterate_out_of_range_notes_and_chords( ... staff)) [Chord('<d fs>8')] Returns generator. ''' from abjad.tools import instrumenttools prototype = (scoretools.Note, scoretools.Chord) for note_or_chord in iterate(expr).by_class(prototype): instrument = note_or_chord._get_effective(instrumenttools.Instrument) if instrument is None: message = 'no instrument found.' raise ValueError(message) if note_or_chord not in instrument.pitch_range: yield note_or_chord
def _apply_preferred_denominator(self, selections, divisions): from abjad.tools import scoretools if not self.preferred_denominator: return tuplets = iterate(selections).by_class(scoretools.Tuplet) tuplets = list(tuplets) if divisions is None: divisions = len(tuplets) * [None] assert len(selections) == len(divisions) assert len(tuplets) == len(divisions) for tuplet, division in zip(tuplets, divisions): if self.preferred_denominator == 'divisions': tuplet.preferred_denominator = division.numerator elif isinstance( self.preferred_denominator, durationtools.Duration): unit_duration = self.preferred_denominator assert unit_duration.numerator == 1 duration = inspect_(tuplet).get_duration() denominator = unit_duration.denominator nonreduced_fraction = duration.with_denominator(denominator) tuplet.preferred_denominator = nonreduced_fraction.numerator elif mathtools.is_positive_integer(self.preferred_denominator): tuplet.preferred_denominator = self.preferred_denominator else: message = 'invalid value for preferred denominator: {!r}.' message = message.format(self.preferred_denominator) raise Exception(message)
def _get_leaves(self): result = [] for component in self._components: for node in iterate(component).depth_first(): if isinstance(node, scoretools.Leaf): result.append(node) return result
def _make_spanner_schema(self): schema = {} spanners = set() for component in iterate(self).by_class(): spanners.update(component._get_spanners()) for spanner in spanners: schema[spanner] = [] for i, component in \ enumerate(iterate(self).by_class()): attached_spanners = component._get_spanners() for attached_spanner in attached_spanners: try: schema[attached_spanner].append(i) except KeyError: pass return schema
def apply_expressive_marks(score): r'''Applies expressive marks to score. ''' voice = score['First Violin Voice'] markup = markuptools.Markup( r'\left-column { div. \line { con sord. } }', Up) attach(markup, voice[6][1]) markup = markuptools.Markup('sim.', Up) attach(markup, voice[8][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[58][3]) markup = markuptools.Markup('div.', Up) attach(markup, voice[59][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[63][3]) voice = score['Second Violin Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[7][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[66][1]) markup = markuptools.Markup('div.', Up) attach(markup, voice[67][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) voice = score['Viola Voice'] markup = markuptools.Markup('sole', Up) attach(markup, voice[8][0]) voice = score['Cello Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[10][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[84][1]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) voice = score['Bass Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[14][0]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) mutate(voice[88][:]).split( [durationtools.Duration(1, 1), durationtools.Duration(1, 2)] ) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[99][1]) strings_staff_group = score['Strings Staff Group'] for voice in iterate(strings_staff_group).by_class(scoretools.Voice): markup = markuptools.Markup(r'\italic { (non dim.) }', Down) attach(markup, voice[102][0])
def __call__(self, expr): for note_or_chord in \ iterate(expr).by_class((scoretools.Note, scoretools.Chord)): #indicatortools.Dynamic(self.dynamic_name)(note_or_chord) command = indicatortools.LilyPondCommand(self.dynamic_name, 'right') attach(command, note_or_chord) return expr
def apply_expressive_marks(score): r'''Applies expressive marks to score. ''' voice = score['First Violin Voice'] markup = markuptools.Markup(r'\left-column { div. \line { con sord. } }', Up) attach(markup, voice[6][1]) markup = markuptools.Markup('sim.', Up) attach(markup, voice[8][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[58][3]) markup = markuptools.Markup('div.', Up) attach(markup, voice[59][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[63][3]) voice = score['Second Violin Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[7][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[66][1]) markup = markuptools.Markup('div.', Up) attach(markup, voice[67][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) voice = score['Viola Voice'] markup = markuptools.Markup('sole', Up) attach(markup, voice[8][0]) voice = score['Cello Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[10][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[84][1]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) voice = score['Bass Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[14][0]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) mutate(voice[88][:]).split( [durationtools.Duration(1, 1), durationtools.Duration(1, 2)]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[99][1]) strings_staff_group = score['Strings Staff Group'] for voice in iterate(strings_staff_group).by_class(scoretools.Voice): markup = markuptools.Markup(r'\italic { (non dim.) }', Down) attach(markup, voice[102][0])
def __init__( self, component=None, cross_offset=None, include_self=True, ): from abjad.tools import scoretools assert isinstance(component, (scoretools.Component, type(None))) if component is None: music = () else: music = list(iterate(component).by_class()) if not include_self: music.remove(component) result = [] if cross_offset is None: result = music else: for x in music: append_x = True if not (x._get_timespan().start_offset < cross_offset and cross_offset < x._get_timespan().stop_offset): append_x = False if append_x: result.append(x) SimultaneousSelection.__init__(self, result) self._component = component
def label_leaves_in_expr_with_pitch_numbers(expr, markup_direction=Down): r'''Label leaves in `expr` with pitch numbers: :: >>> staff = Staff(scoretools.make_leaves([None, 12, [13, 14, 15], None], [(1, 4)])) >>> labeltools.label_leaves_in_expr_with_pitch_numbers(staff) >>> print format(staff) \new Staff { r4 c''4 _ \markup { \small 12 } <cs'' d'' ef''>4 _ \markup { \column { \small 15 \small 14 \small 13 } } r4 } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for leaf in iterate(expr).by_class(scoretools.Leaf): for pitch in reversed(pitchtools.PitchSegment.from_selection(leaf)): if pitch is not None: label = markuptools.MarkupCommand('small', str(pitch.pitch_number)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def add_string_music_to_score(score): r'''Adds string music to score. ''' # generate some pitch and rhythm information pitch_contour_reservoir = \ abjad.demos.part.create_pitch_contour_reservoir() shadowed_contour_reservoir = \ abjad.demos.part.shadow_pitch_contour_reservoir( pitch_contour_reservoir) durated_reservoir = abjad.demos.part.durate_pitch_contour_reservoir( shadowed_contour_reservoir) # add six dotted-whole notes and the durated contours to each string voice for instrument_name, descents in durated_reservoir.items(): instrument_voice = score['%s Voice' % instrument_name] instrument_voice.extend("R1. R1. R1. R1. R1. R1.") for descent in descents: instrument_voice.extend(descent) # apply instrument-specific edits abjad.demos.part.edit_first_violin_voice(score, durated_reservoir) abjad.demos.part.edit_second_violin_voice(score, durated_reservoir) abjad.demos.part.edit_viola_voice(score, durated_reservoir) abjad.demos.part.edit_cello_voice(score, durated_reservoir) abjad.demos.part.edit_bass_voice(score, durated_reservoir) # chop all string parts into 6/4 measures strings_staff_group = score['Strings Staff Group'] with systemtools.ForbidUpdate(score): for voice in iterate(strings_staff_group).by_class(scoretools.Voice): shards = mutate(voice[:]).split([(6, 4)], cyclic=True) for shard in shards: scoretools.Measure((6, 4), shard)
def are_stepwise_notes(self): r'''Is true when notes in selection are stepwise. :: >>> selection_1.are_stepwise_notes() True Otherwise false: :: >>> selection_2.are_stepwise_notes() False Returns boolean. ''' from abjad.tools import scoretools for left, right in sequencetools.iterate_sequence_nwise( iterate(self._client).by_class(scoretools.Note)): try: assert not (left.written_pitch == right.written_pitch) hdi = pitchtools.NamedInterval.from_pitch_carriers(left, right) assert hdi.number <= 2 except AssertionError: return False return True
def reflect(self): r'''Reflect start-positioned rhythm payload expression about axis. :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.reflect() :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ f'8 e'8 d'8 c'8 }" ), start_offset=durationtools.Offset(0, 1), ) Operates in place and returns start-positioned rhythm payload expression. ''' for container in iterate(self.payload).by_class(scoretools.Container): container._music.reverse() for spanner in self.payload._get_descendants().get_spanners(): spanner._reverse_components() return self
def transpose_from_written_pitch_to_sounding_pitch(expr): r'''Transpose notes and chords in `expr` from sounding pitch to written pitch: :: >>> staff = Staff("<c' e' g'>4 d'4 r4 e'4") >>> clarinet = instrumenttools.ClarinetInBFlat() >>> attach(clarinet, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \set Staff.instrumentName = \markup { Clarinet in B-flat } \set Staff.shortInstrumentName = \markup { Cl. in B-flat } <c' e' g'>4 d'4 r4 e'4 } :: >>> instrumenttools.transpose_from_written_pitch_to_sounding_pitch(staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { \set Staff.instrumentName = \markup { Clarinet in B-flat } \set Staff.shortInstrumentName = \markup { Cl. in B-flat } <bf d' f'>4 c'4 r4 d'4 } Returns none. ''' from abjad.tools import instrumenttools prototype = (scoretools.Note, scoretools.Chord) for note_or_chord in iterate(expr).by_class(prototype): instrument = note_or_chord._get_effective(instrumenttools.Instrument) if not instrument: continue sounding_pitch = instrument.sounding_pitch_of_written_middle_c t_n = pitchtools.NamedPitch('C4') - sounding_pitch if isinstance(note_or_chord, scoretools.Note): note_or_chord.written_pitch = \ pitchtools.transpose_pitch_carrier_by_interval( note_or_chord.written_pitch, t_n) elif isinstance(note_or_chord, scoretools.Chord): pitches = [ pitchtools.transpose_pitch_carrier_by_interval(pitch, t_n) for pitch in note_or_chord.written_pitches ] note_or_chord.written_pitches = pitches
def check_misrepresented_flags(self): r'''Checks to make sure there are no misrepresented flags in score. Returns violators and total. ''' from abjad.tools import scoretools from abjad.tools.topleveltools import iterate from abjad.tools.topleveltools import set_ violators = [] total = 0 for leaf in iterate(self.expr).by_class(scoretools.Leaf): total += 1 flags = leaf.written_duration.flag_count left = getattr(set_(leaf), 'stem_left_beam_count', None) right = getattr(set_(leaf), 'stem_right_beam_count', None) if left is not None: if flags < left or \ (left < flags and right not in (flags, None)): if leaf not in violators: violators.append(leaf) if right is not None: if flags < right or \ (right < flags and left not in (flags, None)): if leaf not in violators: violators.append(leaf) return violators, total
def check_overlapping_glissandi(self): r'''Checks to make sure there are no overlapping glissandi in score. Returns violators and total. ''' from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools.topleveltools import iterate violators = [] prototype = (spannertools.Glissando,) for leaf in iterate(self.expr).by_class(scoretools.Leaf): glissandi = leaf._get_spanners(prototype) glissandi = list(glissandi) if 1 < len(glissandi): if len(glissandi) == 2: common_leaves = set(glissandi[0]._leaves) common_leaves &= set(glissandi[1]._leaves) if len(common_leaves) == 1: x = list(common_leaves)[0] if ( (glissandi[0]._is_my_first_leaf(x) and glissandi[1]._is_my_last_leaf(x)) or (glissandi[1]._is_my_first_leaf(x) and glissandi[0]._is_my_last_leaf(x)) ): break for glissando in glissandi: if glissando not in violators: violators.append(glissando) total = self.expr._get_descendants()._get_spanners(prototype) total = len(total) return violators, total
def _check_well_formedness(self, selections): for component in iterate(selections).by_class(): inspector = inspect_(component) if not inspector.is_well_formed(): report = inspector.tabulate_well_formedness_violations() report = repr(component) + '\n' + report raise Exception(report)
def iterate_out_of_range_notes_and_chords(expr): '''Iterates notes and chords in `expr` outside traditional instrument ranges: :: >>> staff = Staff("c'8 r8 <d fs>8 r8") >>> violin = instrumenttools.Violin() >>> attach(violin, staff) :: >>> list( ... instrumenttools.iterate_out_of_range_notes_and_chords( ... staff)) [Chord('<d fs>8')] Returns generator. ''' from abjad.tools import instrumenttools prototype = (scoretools.Note, scoretools.Chord) for note_or_chord in iterate(expr).by_class(prototype): instrument = note_or_chord._get_effective(instrumenttools.Instrument) if instrument is None: message = 'no instrument found.' raise ValueError(message) if note_or_chord not in instrument.pitch_range: yield note_or_chord
def _is_my_only(self, leaf, prototype): i = None components = iterate(self).by_class(prototype) for i, component in enumerate(components): if 0 < i: return False return i == 0
def _apply_output_masks(self, selections): from abjad.tools import rhythmmakertools if not self.output_masks: return selections new_selections = [] duration_spelling_specifier = self.duration_spelling_specifier or \ rhythmmakertools.DurationSpellingSpecifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration length = len(selections) output_masks = self.output_masks for i, selection in enumerate(selections): if not any(_._matches_index(i, length) for _ in output_masks): new_selections.append(selection) continue duration = selection.get_duration() new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def apply_bowing_marks(score): r'''Applies bowing marks to score. ''' # apply alternating upbow and downbow for first two sounding bars # of the first violin for measure in score['First Violin Voice'][6:8]: for i, chord in enumerate(iterate(measure).by_class(scoretools.Chord)): if i % 2 == 0: articulation = indicatortools.Articulation('downbow') attach(articulation, chord) else: articulation = indicatortools.Articulation('upbow') attach(articulation, chord) # create and apply rebowing markup rebow_markup = markuptools.Markup.concat([ markuptools.Markup.musicglyph('scripts.downbow'), markuptools.Markup.hspace(1), markuptools.Markup.musicglyph('scripts.upbow'), ]) markup = copy.copy(rebow_markup) attach(markup, score['First Violin Voice'][64][0]) markup = copy.copy(rebow_markup) attach(markup, score['Second Violin Voice'][75][0]) markup = copy.copy(rebow_markup) attach(markup, score['Viola Voice'][86][0])
def _apply_output_masks(self, selections): from abjad.tools import rhythmmakertools if not self.output_masks: return selections new_selections = [] if self.duration_spelling_specifier is None: duration_spelling_specifier = \ rhythmmakertools.DurationSpellingSpecifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration length = len(selections) output_masks = self.output_masks for i, selection in enumerate(selections): if not any(_._matches_index(i, length) for _ in output_masks): new_selections.append(selection) continue duration = selection.get_duration() new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def apply_final_bar_lines(score): r'''Applies final bar lines to score. ''' for voice in iterate(score).by_class(scoretools.Voice): bar_line = indicatortools.BarLine('|.') attach(bar_line, voice[-1])
def __illustrate__(self): r'''Illustrates pitch segment. :: >>> named_pitch_segment = pitchtools.PitchSegment( ... ['bf,', 'aqs', "fs'", "g'", 'bqf', "g'"], ... item_class=NamedPitch, ... ) >>> show(named_pitch_segment) # doctest: +SKIP Returns LilyPond file. ''' from abjad.tools import durationtools from abjad.tools import lilypondfiletools from abjad.tools import markuptools from abjad.tools import pitchtools from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools.topleveltools import attach from abjad.tools.topleveltools import iterate from abjad.tools.topleveltools import override named_pitches = [pitchtools.NamedPitch(x) for x in self] notes = scoretools.make_notes(named_pitches, [1]) score, treble_staff, bass_staff = \ scoretools.make_piano_sketch_score_from_leaves(notes) for leaf in iterate(score).by_class(scoretools.Leaf): attach(durationtools.Multiplier(1, 8), leaf) override(score).rest.transparent = True lilypond_file = lilypondfiletools.make_basic_lilypond_file(score) lilypond_file.header_block.tagline = markuptools.Markup('""') return lilypond_file
def check_overlapping_glissandi(self): r'''Checks to make sure there are no overlapping glissandi in score. Returns violators and total. ''' from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools.topleveltools import iterate violators = [] prototype = (spannertools.Glissando,) for leaf in iterate(self.expr).by_class(scoretools.Leaf): glissandi = leaf._get_spanners(prototype) if 1 < len(glissandi): if len(glissandi) == 2: common_leaves = set(glissandi[0]._leaves) & \ set(glissandi[1]._leaves) if len(common_leaves) == 1: x = list(common_leaves)[0] if (glissandi[0]._is_my_first_leaf(x) and glissandi[1]._is_my_last_leaf(x)) or \ (glissandi[1]._is_my_first_leaf(x) and glissandi[0]._is_my_last_leaf(x)): break for glissando in glissandi: if glissando not in violators: violators.append(glissando) total = self.expr._get_descendants()._get_spanners(prototype) total = len(total) return violators, total
def are_stepwise_notes(self): r'''Is true when notes in selection are stepwise. :: >>> selection_1.are_stepwise_notes() True Otherwise false: :: >>> selection_2.are_stepwise_notes() False Returns true or false. ''' from abjad.tools import scoretools for left, right in sequencetools.iterate_sequence_nwise( iterate(self._client).by_class(scoretools.Note)): try: assert not (left.written_pitch == right.written_pitch) hdi = pitchtools.NamedInterval.from_pitch_carriers( left, right) assert hdi.number <= 2 except AssertionError: return False return True
def label_leaves_in_expr_with_leaf_indices(expr, markup_direction=Down): r'''Label leaves in `expr` with leaf indices: :: >>> staff = Staff("c'8 d'8 e'8 f'8") >>> labeltools.label_leaves_in_expr_with_leaf_indices(staff) >>> print(format(staff)) \new Staff { c'8 _ \markup { \small 0 } d'8 _ \markup { \small 1 } e'8 _ \markup { \small 2 } f'8 _ \markup { \small 3 } } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for i, leaf in enumerate(iterate(expr).by_class(scoretools.Leaf)): label = markuptools.MarkupCommand('small', str(i)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def _get_my_nth_leaf(self, n): from abjad.tools import scoretools if not isinstance(n, int): raise TypeError if 0 <= n: leaves = iterate(self).by_class(scoretools.Leaf) for leaf_index, leaf in enumerate(leaves): if leaf_index == n: return leaf else: leaves = iterate(self).by_class(scoretools.Leaf, reverse=True) for leaf_index, leaf in enumerate(leaves): leaf_number = -leaf_index - 1 if leaf_number == n: return leaf raise IndexError
def are_scalar_notes(self): r'''Is true when notes in selection are scalar. :: >>> selection_1.are_scalar_notes() True Otherwise false: :: >>> selection_2.are_scalar_notes() False Returns boolean. ''' from abjad.tools import scoretools direction_string = None for left, right in sequencetools.iterate_sequence_nwise( iterate(self._client).by_class(scoretools.Note)): try: assert not (left.written_pitch == right.written_pitch) mdi = pitchtools.NamedInterval.from_pitch_carriers( left, right) assert mdi.number <= 2 if direction_string is None: direction_string = mdi.direction_string assert direction_string == mdi.direction_string except AssertionError: return False return True
def iterate_out_of_range_notes_and_chords(expr): '''Iterates notes and chords in `expr` outside traditional instrument ranges: :: >>> staff = Staff("c'8 r8 <d fs>8 r8") >>> violin = instrumenttools.Violin() >>> attach(violin, staff) :: >>> list( ... instrumenttools.iterate_out_of_range_notes_and_chords( ... staff)) [Chord('<d fs>8')] Returns generator. ''' from abjad.tools import instrumenttools prototype = (scoretools.Note, scoretools.Chord) for note_or_chord in iterate(expr).by_class(prototype): instrument = note_or_chord._get_effective( instrumenttools.Instrument) if instrument is None: message = 'no instrument found.' raise ValueError(message) if note_or_chord not in instrument.pitch_range: yield note_or_chord
def label_leaves_in_expr_with_named_interval_classes(expr, markup_direction=Up): r"""Label leaves in `expr` with named interval classes: :: >>> notes = scoretools.make_notes([0, 25, 11, -4, -14, -13, 9, 10, 6, 5], [Duration(1, 8)]) >>> staff = Staff(notes) >>> labeltools.label_leaves_in_expr_with_named_interval_classes(staff) .. doctest:: >>> print(format(staff)) \new Staff { c'8 ^ \markup { +aug8 } cs'''8 ^ \markup { -M2 } b'8 ^ \markup { -aug2 } af8 ^ \markup { -m7 } bf,8 ^ \markup { aug1 } b,8 ^ \markup { +m7 } a'8 ^ \markup { +m2 } bf'8 ^ \markup { -dim4 } fs'8 ^ \markup { aug1 } f'8 } :: >>> show(staff) # doctest: +SKIP Returns none. """ for note in iterate(expr).by_class(scoretools.Note): logical_voice_iterator = iterate(note).by_logical_voice_from_component( scoretools.Leaf, ) try: next(logical_voice_iterator) next_leaf = next(logical_voice_iterator) if isinstance(next_leaf, scoretools.Note): mdi = pitchtools.NamedInterval.from_pitch_carriers( note, next_leaf) mdic = pitchtools.NamedIntervalClass(mdi) markup = markuptools.Markup(mdic, markup_direction) attach(markup, note) except StopIteration: pass
def add_rhythms_to_score(self): for voice in iterate(self.score).by_class(scoretools.Voice): voice_proxy = \ self.score_specification.voice_data_structures_by_voice[ voice.name] for rhythm_payload_expression in \ voice_proxy.payload_expressions_by_attribute['rhythm']: voice.extend(rhythm_payload_expression.payload)
def score_name(self): r'''Context dictionary score name. Returns string or none. ''' for context in iterate(self.score).by_class(scoretools.Context): if isinstance(context, scoretools.Score): return context.name
def __call__( self, expr, timespan=None, offset=0, skip_first=0, skip_last=0, ): r'''Calls handler on `expr` with keywords. Returns none. ''' articulation_lists = datastructuretools.CyclicTuple( self.articulation_lists) prototype = (scoretools.Note, scoretools.Chord) notes_and_chords = list(iterate(expr).by_class(prototype)) notes_and_chords = notes_and_chords[skip_first:] if skip_last: notes_and_chords = notes_and_chords[:-skip_last] i = 0 for note_or_chord in notes_and_chords: logical_tie = inspect_(note_or_chord).get_logical_tie() duration = logical_tie.get_duration() articulation_list = articulation_lists[offset + i] if articulation_list is None: i += 1 continue articulation_list = [ indicatortools.Articulation(_) for _ in articulation_list ] if self.minimum_duration is not None: if duration <= self.minimum_duration: continue if self.maximum_duration is not None: if self.maximum_duration < duration: continue if self.minimum_written_pitch is not None: if isinstance(note_or_chord, scoretools.Note): minimum_written_pitch = note_or_chord.written_pitch else: minimum_written_pitch = note_or_chord.writen_pitches[0] if minimum_written_pitch < self.minimum_written_pitch: continue if self.maximum_written_pitch is not None: if isinstance(note_or_chord, scoretools.Note): maximum_written_pitch = note_or_chord.written_pitch else: maximum_written_pitch = note_or_chord.written_pitches[-1] if self.maximum_written_pitch < maximum_written_pitch: continue logical_tie = inspect_(note_or_chord).get_logical_tie() if note_or_chord is logical_tie.head: for articulation in articulation_list: # TODO: make new(articulation) work articulation = copy.copy(articulation) attach(articulation, note_or_chord) i += 1 return expr
def _initialize_voice_proxies(self): from experimental.tools import musicexpressiontools voice_names = [] if self.score is not None: for voice in iterate(self.score).by_class(scoretools.Voice): assert voice.context_name is not None, voice.name_name voice_names.append(voice.name) for voice_name in sorted(voice_names): self[voice_name] = musicexpressiontools.VoiceProxy()
def _get_in_my_logical_voice(self, n, component_class=None): if 0 <= n: generator = iterate(self).by_logical_voice_from_component( component_class=component_class, reverse=False, ) for i, component in enumerate(generator): if i == n: return component else: n = abs(n) generator = iterate(self).by_logical_voice_from_component( component_class=component_class, reverse=True, ) for i, component in enumerate(generator): if i == n: return component