示例#1
0
    def __getitem__(self, i):
        r'''Gets container `i`.

        Traverses top-level items only.

        Returns component.
        '''
        if isinstance(i, int):
            return self._music[i]
        elif isinstance(i, slice) and not self.is_simultaneous:
            return selectiontools.SliceSelection(self._music[i])
        elif isinstance(i, slice) and self.is_simultaneous:
            return selectiontools.SimultaneousSelection(self._music[i])
        elif isinstance(i, str):
            if i not in self._named_children:
                message = 'can not find component named {!r}.'
                message = message.format(i)
                raise ValueError(message)
            elif 1 < len(self._named_children[i]):
                message = 'multiple components named {!r}.'
                message = message.format(i)
                raise ValueError(message)
            return self._named_children[i][0]
        message = 'can not get container item {!r}.'
        message = message.format(i)
        raise ValueError(message)
示例#2
0
 def _initialize_music(self, music):
     from abjad.tools import scoretools
     Selection = selectiontools.Selection
     if music is None:
         music = []
     if self._all_are_orphan_components(music):
         self._music = list(music)
         self[:]._set_parents(self)
     elif Selection._all_are_contiguous_components_in_same_logical_voice(
         music):
         music = selectiontools.SliceSelection(music)
         parent, start, stop = music._get_parent_and_start_stop_indices()
         self._music = list(music)
         self[:]._set_parents(self)
         assert parent is not None
         parent._music.insert(start, self)
         self._set_parent(parent)
     elif isinstance(music, str):
         parsed = self._parse_string(music)
         self._music = []
         self.is_simultaneous = parsed.is_simultaneous
         if parsed.is_simultaneous or \
             not Selection._all_are_contiguous_components_in_same_logical_voice(
             parsed[:]):
             while len(parsed):
                 self.append(parsed.pop(0))
         else:
             self[:] = parsed[:]
     else:
         message = 'can not initialize container from {!r}.'
         message = message.format((music))
         raise TypeError(message)
示例#3
0
 def _get_contents(self, include_self=True):
     result = []
     if include_self:
         result.append(self)
     result.extend(getattr(self, '_music', []))
     result = selectiontools.SliceSelection(result)
     return result
示例#4
0
 def _extract(self, scale_contents=None):
     from abjad.tools import selectiontools
     selection = selectiontools.SliceSelection([self])
     parent, start, stop = selection._get_parent_and_start_stop_indices()
     music_list = list(getattr(self, '_music', ()))
     parent.__setitem__(slice(start, stop + 1), music_list)
     return self
示例#5
0
    def get_counttime_components(self, counttime_components):
        r'''Get `counttime_components` that satisfy `time_relation`:

        ::

            >>> voice = Voice(
            ...     [Note(i % 36, Duration(1, 4)) for i in range(200)])
            >>> timespan_1 = timespantools.Timespan(20, 22)
            >>> time_relation = \
            ...     timespantools.timespan_2_starts_during_timespan_1(
            ...     timespan_1=timespan_1)

        ::

            >>> result = time_relation.get_counttime_components(voice[:])

        ::

            >>> for counttime_component in result:
            ...     counttime_component
            Note("af'4")
            Note("a'4")
            Note("bf'4")
            Note("b'4")
            Note("c''4")
            Note("cs''4")
            Note("d''4")
            Note("ef''4")

        ::

            >>> result.get_timespan()
            Timespan(start_offset=Offset(20, 1), stop_offset=Offset(22, 1))

        `counttime_components` must belong to a single voice.

        `counttime_components` must be time-contiguous.

        The call shown here takes 78355 function calls under r9686.

        Returns selection.
        '''
        from abjad.tools import selectiontools
        from abjad.tools import timespantools

        # check input
        assert isinstance(
            counttime_components,
            (list, selectiontools.SliceSelection)), repr(counttime_components)
        assert self.timespan_1 is not None

        # iterate counttime components
        result = []
        for counttime_component in counttime_components:
            if self(timespan_2=counttime_component._get_timespan()):
                result.append(counttime_component)

        # return result
        return selectiontools.SliceSelection(result)
示例#6
0
    def __delitem__(self, i):
        r'''Deletes container `i`.
        Detaches component(s) from parentage.
        Withdraws component(s) from crossing spanners.
        Preserves spanners that component(s) cover(s).

        Returns none.
        '''
        components = self[i]
        #if not isinstance(components, selectiontools.SliceSelection):
        if not isinstance(components, selectiontools.Selection):
            components = selectiontools.SliceSelection([components])
        if not self.is_simultaneous:
            components._withdraw_from_crossing_spanners()
        components._set_parents(None)
示例#7
0
 def _fuse_measures(self):
     from abjad.tools import scoretools
     from abjad.tools import selectiontools
     # check input
     prototype=(scoretools.Measure,)
     assert self._all_are_contiguous_components_in_same_parent(
         self, prototype)
     # return none on empty measures
     if len(self) == 0:
         return None
     # TODO: instantiate a new measure
     #       instead of returning a reference to existing measure
     if len(self) == 1:
         return self[0]
     implicit_scaling = self[0].implicit_scaling
     assert all(
         x.implicit_scaling == implicit_scaling for x in self)
     selection = selectiontools.SliceSelection(self)
     parent, start, stop = selection._get_parent_and_start_stop_indices()
     old_denominators = []
     new_duration = durationtools.Duration(0)
     for measure in self:
         effective_time_signature = measure.time_signature
         old_denominators.append(effective_time_signature.denominator)
         new_duration += effective_time_signature.duration
     new_time_signature = \
         measure._duration_and_possible_denominators_to_time_signature(
         new_duration,
         old_denominators,
         )
     music = []
     for measure in self:
         # scale before reassignment to prevent logical tie scale drama
         signature = measure.time_signature
         prolation = signature.implied_prolation
         multiplier = prolation / new_time_signature.implied_prolation
         measure._scale_contents(multiplier)
         measure_music = measure[:]
         measure_music._set_parents(None)
         music += measure_music
     new_measure = scoretools.Measure(new_time_signature, music)
     new_measure.implicit_scaling = self[0].implicit_scaling
     if parent is not None:
         self._give_dominant_spanners([new_measure])
     self._set_parents(None)
     if parent is not None:
         parent.insert(start, new_measure)
     return new_measure
示例#8
0
 def _next_in_parent(component):
     from abjad.tools import selectiontools
     if not isinstance(component, scoretools.Component):
         raise TypeError
     selection = selectiontools.SliceSelection(component)
     parent, start, stop = \
         selection._get_parent_and_start_stop_indices()
     assert start == stop
     if parent is None:
         raise StopIteration
     # can not advance within simultaneous parent
     if parent.is_simultaneous:
         raise StopIteration
     try:
         return parent[start + 1]
     except IndexError:
         raise StopIteration
示例#9
0
 def _split(
     self,
     durations,
     cyclic=False,
     fracture_spanners=False,
     tie_split_notes=True,
     use_messiaen_style_ties=False,
     ):
     from abjad.tools import pitchtools
     from abjad.tools import selectiontools
     from abjad.tools import scoretools
     from abjad.tools import spannertools
     durations = [durationtools.Duration(x) for x in durations]
     if cyclic:
         durations = sequencetools.repeat_sequence_to_weight(
             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(
         durations,
         weight=self._get_duration(),
         )
     result = []
     leaf_prolation = self._get_parentage(include_self=False).prolation
     timespan = self._get_timespan()
     start_offset = timespan.start_offset
     for duration in durations:
         new_leaf = copy.copy(self)
         preprolated_duration = duration / leaf_prolation
         shard = new_leaf._set_duration(
             preprolated_duration,
             use_messiaen_style_ties=use_messiaen_style_ties,
             )
         for x in shard:
             if isinstance(x, scoretools.Leaf):
                 x_duration = x.written_duration * leaf_prolation
             else:
                 x_duration = x.multiplied_duration * leaf_prolation
             stop_offset = x_duration + start_offset
             x._start_offset = start_offset
             x._stop_offset = stop_offset
             x._timespan = timespantools.Timespan(
                 start_offset=start_offset,
                 stop_offset=stop_offset,
                 )
             start_offset = stop_offset
         shard = [x._get_parentage().root for x in shard]
         result.append(shard)
     flattened_result = sequencetools.flatten_sequence(result)
     flattened_result = selectiontools.SliceSelection(flattened_result)
     prototype = (spannertools.Tie,)
     parentage = self._get_parentage()
     if parentage._get_spanners(prototype=prototype):
         selection = select(flattened_result)
         for component in selection:
             # TODO: make top-level detach() work here
             for spanner in component._get_spanners(prototype):
                 spanner._sever_all_components()
             #detach(prototype, component)
     # 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')
         detach(object, middle_leaf)
     # adjust last leaf
     last_leaf = flattened_result[-1]
     last_leaf._detach_grace_containers(kind='grace')
     detach(object, last_leaf)
     # tie split notes, rests and chords as specified
     if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes:
         flattened_result_leaves = iterate(flattened_result).by_class(
             scoretools.Leaf)
         # TODO: implement SliceSelection._attach_tie_spanner_to_leaves()
         for leaf_pair in sequencetools.iterate_sequence_nwise(
             flattened_result_leaves):
             selection = selectiontools.ContiguousSelection(leaf_pair)
             selection._attach_tie_spanner_to_leaf_pair(
                 use_messiaen_style_ties=use_messiaen_style_ties,
                 )
     # return result
     return result
示例#10
0
    def by_run(self, classes):
        r'''Iterate runs in expression.

        ..  container:: example

            **Example 1.** Iterate runs of notes and chords at only the
            top level of score:

            ::

                >>> staff = Staff(r"\times 2/3 { c'8 d'8 r8 }")
                >>> staff.append(r"\times 2/3 { r8 <e' g'>8 <f' a'>8 }")
                >>> staff.extend("g'8 a'8 r8 r8 <b' d''>8 <c'' e''>8")

            ..  doctest::

                >>> print(format(staff))
                \new Staff {
                    \times 2/3 {
                        c'8
                        d'8
                        r8
                    }
                    \times 2/3 {
                        r8
                        <e' g'>8
                        <f' a'>8
                    }
                    g'8
                    a'8
                    r8
                    r8
                    <b' d''>8
                    <c'' e''>8
                }

            ::

                >>> for group in iterate(staff[:]).by_run((Note, Chord)):
                ...     group
                ...
                (Note("g'8"), Note("a'8"))
                (Chord("<b' d''>8"), Chord("<c'' e''>8"))

        ..  container:: example

            **Example 2.** Iterate runs of notes and chords at all levels of
            score:

            ::

                >>> leaves = iterate(staff).by_class(scoretools.Leaf)

            ::

                >>> for group in iterate(leaves).by_run((Note, Chord)):
                ...     group
                ...
                (Note("c'8"), Note("d'8"))
                (Chord("<e' g'>8"), Chord("<f' a'>8"), Note("g'8"), Note("a'8"))
                (Chord("<b' d''>8"), Chord("<c'' e''>8"))

        Returns generator.
        '''
        from abjad.tools import selectiontools
        sequence = selectiontools.SliceSelection(self._client)
        current_group = ()
        for group in sequence.group_by(type):
            if type(group[0]) in classes:
                current_group = current_group + group
            elif current_group:
                yield current_group
                current_group = ()
        if current_group:
            yield current_group
示例#11
0
    def _split_at_index(
        self,
        i,
        fracture_spanners=False,
    ):
        r'''Splits container to the left of index `i`.

        Preserves tuplet multiplier when container is a tuplet.

        Preserves time signature denominator when container is a measure.

        Resizes resizable containers.

        Returns split parts.
        '''
        from abjad.tools import indicatortools
        from abjad.tools import scoretools
        from abjad.tools import selectiontools
        from abjad.tools import spannertools
        # partition my music
        left_music = self[:i]
        right_music = self[i:]
        # instantiate new left and right containers
        if isinstance(self, scoretools.Measure):
            time_signature = self._get_effective(indicatortools.TimeSignature)
            denominator = time_signature.denominator
            left_duration = sum([x._get_duration() for x in left_music])
            left_pair = mathtools.NonreducedFraction(left_duration)
            left_pair = left_pair.with_multiple_of_denominator(denominator)
            left_time_signature = indicatortools.TimeSignature(left_pair)
            left = type(self)(left_time_signature, left_music)
            left.implicit_scaling = self.implicit_scaling
            right_duration = sum([x._get_duration() for x in right_music])
            right_pair = mathtools.NonreducedFraction(right_duration)
            right_pair = right_pair.with_multiple_of_denominator(denominator)
            right_time_signature = indicatortools.TimeSignature(right_pair)
            right = type(self)(right_time_signature, right_music)
            right.implicit_scaling = self.implicit_scaling
        elif isinstance(self, scoretools.FixedDurationTuplet):
            multiplier = self.multiplier
            left = type(self)(1, left_music)
            right = type(self)(1, right_music)
            target_duration = multiplier * left._contents_duration
            left.target_duration = target_duration
            target_duration = multiplier * right._contents_duration
            right.target_duration = target_duration
        elif isinstance(self, scoretools.Tuplet):
            multiplier = self.multiplier
            left = type(self)(multiplier, left_music)
            right = type(self)(multiplier, right_music)
        else:
            left = type(self)(left_music)
            right = type(self)(right_music)
        # save left and right containers together for iteration
        halves = (left, right)
        nonempty_halves = [half for half in halves if len(half)]
        # give my attached spanners to my children
        self._move_spanners_to_children()
        # incorporate left and right parents in score if possible
        selection = selectiontools.SliceSelection(self)
        parent, start, stop = selection._get_parent_and_start_stop_indices()
        if parent is not None:
            parent._music.__setitem__(slice(start, stop + 1), nonempty_halves)
            for part in nonempty_halves:
                part._set_parent(parent)
        else:
            left._set_parent(None)
            right._set_parent(None)
        # fracture spanners if requested
        if fracture_spanners:
            for spanner in left._get_spanners():
                index = spanner._index(left)
                spanner._fracture(index, direction=Right)
        # return new left and right containers
        return halves
示例#12
0
    def _set_item(
        self,
        i,
        expr,
        withdraw_components_in_expr_from_crossing_spanners=True,
    ):
        r'''This method exists because __setitem__ can not accept keywords.
        Note that setting
        withdraw_components_in_expr_from_crossing_spanners=False constitutes a
        composer-unsafe use of this method. Only private methods should set
        this keyword.
        '''
        from abjad.tools import scoretools
        from abjad.tools import selectiontools
        # cache indicators attached to components in expr
        expr_indicators = []
        for component in iterate(expr).by_class():
            indicators = component._get_indicators(unwrap=False)
            expr_indicators.extend(indicators)
        # item assignment
        if isinstance(i, int):
            if isinstance(expr, str):
                expr = self._parse_string(expr)[:]
                assert len(expr) == 1, repr(expr)
                expr = expr[0]
            else:
                expr = [expr]
            if i < 0:
                i = len(self) + i
            i = slice(i, i + 1)
        else:
            if isinstance(expr, str):
                expr = self._parse_string(expr)[:]
            elif (isinstance(expr, list) and len(expr) == 1
                  and isinstance(expr[0], str)):
                expr = self._parse_string(expr[0])[:]

        prototype = (scoretools.Component, selectiontools.Selection)
        assert all(isinstance(x, prototype) for x in expr)

        new_expr = []
        for item in expr:
            if isinstance(item, selectiontools.Selection):
                new_expr.extend(item)
            else:
                new_expr.append(item)
        expr = new_expr

        assert all(isinstance(x, scoretools.Component) for x in expr)
        if any(isinstance(x, scoretools.GraceContainer) for x in expr):
            message = 'must attach grace container to note or chord.'
            raise Exception(message)
        if self._check_for_cycles(expr):
            raise ParentageError('Attempted to induce cycles.')
        if (i.start == i.stop and i.start is not None and i.stop is not None
                and i.start <= -len(self)):
            start, stop = 0, 0
        else:
            start, stop, stride = i.indices(len(self))
        old = self[start:stop]
        spanners_receipt = self._get_spanners_that_dominate_slice(start, stop)
        #print('RECEIPT', spanners_receipt, self, expr)

        for component in old:
            for child in iterate([component]).by_class():
                for spanner in child._get_spanners():
                    spanner._remove(child)
        del (self[start:stop])

        # must withdraw before setting in self!
        # otherwise circular withdraw ensues!
        if withdraw_components_in_expr_from_crossing_spanners:
            selection = selectiontools.SliceSelection(expr)
            if selection._all_are_contiguous_components_in_same_logical_voice(
                    selection):
                selection._withdraw_from_crossing_spanners()
        self._music.__setitem__(slice(start, start), expr)
        for component in expr:
            component._set_parent(self)
        for spanner, index in spanners_receipt:
            for component in reversed(expr):
                spanner._insert(index, component)
                component._spanners.add(spanner)

        for indicator in expr_indicators:
            if hasattr(indicator, '_update_effective_context'):
                indicator._update_effective_context()
示例#13
0
 def _splice(
     self,
     components,
     direction=Right,
     grow_spanners=True,
     ):
     from abjad.tools import scoretools
     from abjad.tools import selectiontools
     assert all(isinstance(x, scoretools.Component) for x in components)
     selection = selectiontools.ContiguousSelection(self)
     if direction == Right:
         if grow_spanners:
             insert_offset = self._get_timespan().stop_offset
             receipt = selection._get_dominant_spanners()
             for spanner, index in receipt:
                 insert_component = None
                 for component in spanner:
                     start_offset = component._get_timespan().start_offset
                     if start_offset == insert_offset:
                         insert_component = component
                         break
                 if insert_component is not None:
                     insert_index = spanner._index(insert_component)
                 else:
                     insert_index = len(spanner)
                 for component in reversed(components):
                     spanner._insert(insert_index, component)
                     component._spanners.add(spanner)
         selection = selectiontools.SliceSelection(self)
         parent, start, stop = \
             selection._get_parent_and_start_stop_indices()
         if parent is not None:
             if grow_spanners:
                 for component in reversed(components):
                     component._set_parent(parent)
                     parent._music.insert(start + 1, component)
             else:
                 after = stop + 1
                 parent.__setitem__(slice(after, after), components)
         return [self] + components
     else:
         if grow_spanners:
             offset = self._get_timespan().start_offset
             receipt = selection._get_dominant_spanners()
             for spanner, x in receipt:
                 for component in spanner:
                     if component._get_timespan().start_offset == offset:
                         index = spanner._index(component)
                         break
                 else:
                     message = 'no component in spanner at offset.'
                     raise ValueError(message)
                 for component in reversed(components):
                     spanner._insert(index, component)
                     component._spanners.add(spanner)
         selection = selectiontools.SliceSelection(self)
         parent, start, stop = \
             selection._get_parent_and_start_stop_indices()
         if parent is not None:
             if grow_spanners:
                 for component in reversed(components):
                     component._set_parent(parent)
                     parent._music.insert(start, component)
             else:
                 parent.__setitem__(slice(start, start), components)
         return components + [self]