def __or__(self, expr): r'''Logical OR of two payload expressions. Payload expression must be able to fuse. Returns timespan inventory. ''' assert self._can_fuse(expr) if isinstance(self.payload, containertools.Container): selection = select(self.payload[0], contiguous=True) left = mutationtools.mutate(selection).copy()[0] selection = select(expr.payload[0], contiguous=True) right = mutationtools.mutate(selection).copy()[0] payload = containertools.Container([left, right]) for component in payload[:]: component._extract() payload = containertools.Container([payload]) else: payload = self.payload + expr.payload result = type(self)( [], start_offset=self.timespan.start_offset, voice_name=self.voice_name, ) result._payload = payload return timespantools.TimespanInventory([result])
def from_selection(cls, selection, item_class=None, name=None): r'''Initialize pitch segment from component selection: :: >>> staff_1 = Staff("c'4 <d' fs' a'>4 b2") >>> staff_2 = Staff("c4. r8 g2") >>> selection = select((staff_1, staff_2)) >>> pitchtools.PitchSegment.from_selection(selection) PitchSegment(["c'", "d'", "fs'", "a'", 'b', 'c', 'g']) Returns pitch segment. ''' from abjad.tools import iterationtools from abjad.tools import pitchtools from abjad.tools import selectiontools if not isinstance(selection, selectiontools.Selection): selection = selectiontools.select(selection) named_pitches = [] for component in iterationtools.iterate_notes_and_chords_in_expr( selection): if hasattr(component, 'written_pitches'): named_pitches.extend(component.written_pitches) elif hasattr(component, 'written_pitch'): named_pitches.append(component.written_pitch) return cls( tokens=named_pitches, item_class=item_class, name=name, )
def add_double_bar(self): r'''Add double bar to end of score. >>> staff = Staff("c'4 d'4 e'4 f'4") >>> score = Score([staff]) .. doctest:: >>> f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 } >> :: >>> show(score) # doctest: +SKIP :: >>> score.add_double_bar() BarLine('|.')(f'4) .. doctest:: >>> f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 \bar "|." } >> :: >>> show(score) # doctest: +SKIP Returns bar line. ''' from abjad.tools import leaftools from abjad.tools import marktools from abjad.tools import selectiontools from abjad.tools.scoretools import attach selection = selectiontools.select(self) last_leaf = selection._get_component(leaftools.Leaf, -1) double_bar = marktools.BarLine('|.') attach(double_bar, last_leaf) return double_bar
def get_one_indexed_measure_number_in_expr(expr, measure_number): r'''Gets one-indexed `measure_number` in `expr`. :: >>> staff = Staff("abj: | 2/8 c'8 d'8 || 2/8 e'8 f'8 || 2/8 g'8 a'8 |") >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { { \time 2/8 c'8 d'8 } { e'8 f'8 } { g'8 a'8 } } :: >>> measuretools.get_one_indexed_measure_number_in_expr(staff, 3) Measure(2/8, [g'8, a'8]) Note that measures number from ``1``. ''' from abjad.tools import measuretools from abjad.tools import selectiontools # check input if measure_number < 1: raise ValueError('measure numbers allow only positive integers.') # calculate measure index measure_index = measure_number - 1 # return measure selection = selectiontools.select(expr) return selection._get_component(measuretools.Measure, measure_index)
def add_final_markup(self, markup, extra_offset=None): r'''Add `markup` to end of score: :: >>> staff = Staff("c'4 d'4 e'4 f'4") >>> score = Score([staff]) >>> markup = r'\italic \right-column { "Bremen - Boston - LA." "Jul 2010 - May 2011." }' >>> markup = markuptools.Markup(markup, Down) >>> markup = score.add_final_markup(markup, extra_offset=(4, -2)) :: >>> print markup.storage_format markuptools.Markup(( markuptools.MarkupCommand( 'italic', markuptools.MarkupCommand( 'right-column', [ 'Bremen - Boston - LA.', 'Jul 2010 - May 2011.' ] ) ), ), direction=Down ) .. doctest:: >>> f(score) \new Score << \new Staff { c'4 d'4 e'4 \once \override TextScript #'extra-offset = #'(4 . -2) f'4 _ \markup { \italic \right-column { "Bremen - Boston - LA." "Jul 2010 - May 2011." } } } >> :: >>> show(staff) # doctest: +SKIP Return `markup`. ''' from abjad.tools import markuptools from abjad.tools import leaftools from abjad.tools import selectiontools from abjad.tools.scoretools import attach selection = selectiontools.select(self) last_leaf = selection._get_component(leaftools.Leaf, -1) # TODO: copy markup direction from markup input markup = markup = markuptools.Markup(markup, Down) attach(markup, last_leaf) if extra_offset is not None: last_leaf.override.text_script.extra_offset = extra_offset return markup
def _split( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, ): from abjad.tools import iterationtools from abjad.tools import pitchtools from abjad.tools import selectiontools from abjad.tools import spannertools durations = [durationtools.Duration(x) for x in durations] if cyclic: durations = sequencetools.repeat_sequence_to_weight_exactly( durations, self._get_duration()) durations = [durationtools.Duration(x) for x in durations] if sum(durations) < self._get_duration(): last_duration = self._get_duration() - sum(durations) durations.append(last_duration) sequencetools.truncate_sequence_to_weight( durations, self._get_duration()) result = [] leaf_prolation = self._get_parentage(include_self=False).prolation leaf_copy = copy.copy(self) for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation shard = new_leaf._set_duration(preprolated_duration) shard = [x._get_parentage().root for x in shard] result.append(shard) flattened_result = sequencetools.flatten_sequence(result) flattened_result = selectiontools.SliceSelection(flattened_result) spanner_classes = (spannertools.TieSpanner,) parentage = self._get_parentage() if parentage._get_spanners(spanner_classes=spanner_classes): selection = selectiontools.select(flattened_result) for component in selection: for mark in component._get_spanners( spanner_classes=spanner_classes): mark.detach() # replace leaf with flattened result selection = selectiontools.SliceSelection(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), flattened_result) else: selection._give_dominant_spanners(flattened_result) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_shard = result[0] for spanner in first_shard[-1]._get_spanners(): index = spanner.index(first_shard[-1]) spanner.fracture(index, direction=Right) last_shard = result[-1] for spanner in last_shard[0]._get_spanners(): index = spanner.index(last_shard[0]) spanner.fracture(index, direction=Left) for middle_shard in result[1:-1]: for spanner in middle_shard[0]._get_spanners(): index = spanner.index(middle_shard[0]) spanner.fracture(index, direction=Left) for spanner in middle_shard[-1]._get_spanners(): index = spanner.index(middle_shard[-1]) spanner.fracture(index, direction=Right) # adjust first leaf first_leaf = flattened_result[0] self._detach_grace_containers(kind='after') # adjust any middle leaves for middle_leaf in flattened_result[1:-1]: middle_leaf._detach_grace_containers(kind='grace') self._detach_grace_containers(kind='after') for mark in middle_leaf._get_marks(): mark.detach() # adjust last leaf last_leaf = flattened_result[-1] last_leaf._detach_grace_containers(kind='grace') for mark in last_leaf._get_marks(): mark.detach() # tie split notes, rests and chords as specified if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes: flattened_result_leaves = iterationtools.iterate_leaves_in_expr( flattened_result) # TODO: implement SliceSelection._attach_tie_spanner_to_leaves() for leaf_pair in sequencetools.iterate_sequence_pairwise_strict( flattened_result_leaves): selection = selectiontools.ContiguousSelection(leaf_pair) selection._attach_tie_spanner_to_leaf_pair() # return result return result