Ejemplo n.º 1
0
    def __illustrate__(self,
                       markup_direction=enums.Up,
                       figure_name=None,
                       **keywords):
        """
        Illustrates segment.

        Returns LilyPond file.
        """
        import abjad
        notes = []
        for item in self:
            note = abjad.Note(item, Duration(1, 8))
            notes.append(note)
        markup = None
        if self._equivalence_markup:
            markup = self._equivalence_markup
        if isinstance(figure_name, str):
            figure_name = abjad.Markup(figure_name)
        if figure_name is not None:
            markup = figure_name
        if markup is not None:
            direction = markup_direction
            markup = abjad.new(markup, direction=direction)
            abjad.attach(markup, notes[0])
        voice = abjad.Voice(notes)
        staff = abjad.Staff([voice])
        score = abjad.Score([staff])
        score.add_final_bar_line()
        abjad.override(score).bar_line.transparent = True
        abjad.override(score).bar_number.stencil = False
        abjad.override(score).beam.stencil = False
        abjad.override(score).flag.stencil = False
        abjad.override(score).stem.stencil = False
        abjad.override(score).time_signature.stencil = False
        string = r'\override Score.BarLine.transparent = ##f'
        command = abjad.LilyPondLiteral(string, 'after')
        last_leaf = abjad.select(score).leaves()[-1]
        abjad.attach(command, last_leaf)
        moment = abjad.SchemeMoment((1, 12))
        abjad.setting(score).proportional_notation_duration = moment
        lilypond_file = abjad.LilyPondFile.new(music=score)
        if 'title' in keywords:
            title = keywords.get('title')
            if not isinstance(title, abjad.Markup):
                title = abjad.Markup(title)
            lilypond_file.header_block.title = title
        if 'subtitle' in keywords:
            markup = abjad.Markup(keywords.get('subtitle'))
            lilypond_file.header_block.subtitle = markup
        command = abjad.LilyPondLiteral(r'\accidentalStyle forget')
        lilypond_file.layout_block.items.append(command)
        lilypond_file.layout_block.indent = 0
        string = 'markup-system-spacing.padding = 8'
        command = abjad.LilyPondLiteral(string)
        lilypond_file.paper_block.items.append(command)
        string = 'system-system-spacing.padding = 10'
        command = abjad.LilyPondLiteral(string)
        lilypond_file.paper_block.items.append(command)
        string = 'top-markup-spacing.padding = 4'
        command = abjad.LilyPondLiteral(string)
        lilypond_file.paper_block.items.append(command)
        return lilypond_file
Ejemplo n.º 2
0
 def written_duration(self, argument):
     duration = Duration(argument)
     if not duration.is_assignable:
         message = f'not assignable duration: {duration!r}.'
         raise exceptions.AssignabilityError(message)
     self._written_duration = duration
Ejemplo n.º 3
0
    def __init__(
        self, *arguments, multiplier: typings.DurationTyping = None, tag: Tag = None,
    ) -> None:
        from abjad.ly import drums
        from .Note import Note

        assert len(arguments) in (0, 1, 2)
        self._note_heads = NoteHeadList(client=self)
        if len(arguments) == 1 and isinstance(arguments[0], str):
            string = f"{{ {arguments[0]} }}"
            parsed = parse(string)
            assert len(parsed) == 1 and isinstance(parsed[0], Leaf)
            arguments = tuple([parsed[0]])
        are_cautionary: typing.List[typing.Optional[bool]] = []
        are_forced: typing.List[typing.Optional[bool]] = []
        are_parenthesized: typing.List[typing.Optional[bool]] = []
        if len(arguments) == 1 and isinstance(arguments[0], Leaf):
            leaf = arguments[0]
            written_pitches = []
            written_duration = leaf.written_duration
            if multiplier is None:
                multiplier = leaf.multiplier
            # TODO: move to dedicated from_note() constructor:
            if isinstance(leaf, Note) and leaf.note_head is not None:
                written_pitches.append(leaf.note_head.written_pitch)
                are_cautionary = [leaf.note_head.is_cautionary]
                are_forced = [leaf.note_head.is_forced]
                are_parenthesized = [leaf.note_head.is_parenthesized]
            elif isinstance(leaf, Chord):
                written_pitches.extend(x.written_pitch for x in leaf.note_heads)
                are_cautionary = [x.is_cautionary for x in leaf.note_heads]
                are_forced = [x.is_forced for x in leaf.note_heads]
                are_parenthesized = [x.is_parenthesized for x in leaf.note_heads]
        # TODO: move to dedicated constructor:
        elif len(arguments) == 2:
            written_pitches, written_duration = arguments
            if isinstance(written_pitches, str):
                written_pitches = [x for x in written_pitches.split() if x]
            elif isinstance(written_pitches, type(self)):
                written_pitches = written_pitches.written_pitches
        elif len(arguments) == 0:
            written_pitches = [abjad_pitch.NamedPitch(_) for _ in [0, 4, 7]]
            written_duration = Duration(1, 4)
        else:
            raise ValueError(f"can not initialize chord from {arguments!r}.")
        Leaf.__init__(self, written_duration, multiplier=multiplier, tag=tag)
        if not are_cautionary:
            are_cautionary = [None] * len(written_pitches)
        if not are_forced:
            are_forced = [None] * len(written_pitches)
        if not are_parenthesized:
            are_parenthesized = [None] * len(written_pitches)
        for written_pitch, is_cautionary, is_forced, is_parenthesized in zip(
            written_pitches, are_cautionary, are_forced, are_parenthesized
        ):
            if not is_cautionary:
                is_cautionary = None
            if not is_forced:
                is_forced = None
            if not is_parenthesized:
                is_parenthesized = None
            if written_pitch not in drums:
                note_head = NoteHead(
                    written_pitch=written_pitch,
                    is_cautionary=is_cautionary,
                    is_forced=is_forced,
                    is_parenthesized=is_parenthesized,
                )
            else:
                assert isinstance(written_pitch, str), repr(written_pitch)
                note_head = DrumNoteHead(
                    written_pitch=written_pitch,
                    is_cautionary=is_cautionary,
                    is_forced=is_forced,
                    is_parenthesized=is_parenthesized,
                )
            self._note_heads.append(note_head)
        if len(arguments) == 1 and isinstance(arguments[0], Leaf):
            self._copy_override_and_set_from_leaf(arguments[0])
Ejemplo n.º 4
0
 def _get_multiplied_duration(self):
     if self.written_duration:
         if self.multiplier is not None:
             duration = self.multiplier * self.written_duration
             return Duration(duration)
         return Duration(self.written_duration)
Ejemplo n.º 5
0
    def _split_by_durations(
        self,
        durations,
        cyclic=False,
        tie_split_notes=True,
        repeat_ties=False,
        ):
        from .AfterGraceContainer import AfterGraceContainer
        from .Chord import Chord
        from .GraceContainer import GraceContainer
        from .Note import Note
        from .Selection import Selection
        from .Tuplet import Tuplet
        durations = [Duration(_) for _ in durations]
        durations = Sequence(durations)
        leaf_duration = inspect(self).duration()
        if cyclic:
            durations = durations.repeat_to_weight(leaf_duration)
        if sum(durations) < leaf_duration:
            last_duration = leaf_duration - sum(durations)
            durations = list(durations)
            durations.append(last_duration)
            durations = Sequence(durations)
        durations = durations.truncate(weight=leaf_duration)
        originally_tied = inspect(self).has_indicator(TieIndicator)
        originally_repeat_tied = inspect(self).has_indicator(RepeatTie)
        result_selections = []
        grace_container = self._detach_grace_container()
        after_grace_container = self._detach_after_grace_container()
        leaf_prolation = inspect(self).parentage().prolation
        for duration in durations:
            new_leaf = copy.copy(self)
            preprolated_duration = duration / leaf_prolation
            selection = new_leaf._set_duration(
                preprolated_duration,
                repeat_ties=repeat_ties,
                )
            result_selections.append(selection)
        result_components = Sequence(result_selections).flatten(depth=-1)
        result_components = select(result_components)
        result_leaves = select(result_components).leaves(grace_notes=False)
        assert all(isinstance(_, Selection) for _ in result_selections)
        assert all(isinstance(_, Component) for _ in result_components)
        assert result_leaves.are_leaves()
#        for leaf in result_leaves:
#            detach(Tie, leaf)
        # strip result leaves of all indicators
        for leaf in result_leaves:
            detach(object, leaf)
        # replace leaf with flattened result
        if self._parent is not None:
            mutate(self).replace(result_components)
        # move indicators
        first_result_leaf = result_leaves[0]
        last_result_leaf = result_leaves[-1]
        for indicator in inspect(self).indicators():
            detach(indicator, self)
            direction = getattr(indicator, '_time_orientation', enums.Left)
            if direction is enums.Left:
                attach(indicator, first_result_leaf)
            elif direction == enums.Right:
                attach(indicator, last_result_leaf)
            else:
                raise ValueError(direction)
        # move grace containers
        if grace_container is not None:
            container = grace_container[0]
            assert isinstance(container, GraceContainer), repr(container)
            attach(container, first_result_leaf)
        if after_grace_container is not None:
            container = after_grace_container[0]
            prototype = AfterGraceContainer
            assert isinstance(container, prototype), repr(container)
            attach(container, last_result_leaf)
        if isinstance(result_components[0], Tuplet):
            mutate(result_components).fuse()
        # tie split notes
        if (tie_split_notes and
            isinstance(self, (Note, Chord)) and
            1 < len(result_leaves)):
            result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties)
        #assert not inspect(result_leaves[0]).has_indicator(RepeatTie)
        detach(RepeatTie, result_leaves[0])
        #assert not inspect(result_leaves[-1]).has_indicator(TieIndicator)
        detach(TieIndicator, result_leaves[-1])
        if originally_repeat_tied:
            tie = RepeatTie()
            attach(tie, result_leaves[0])
        if originally_tied:
            tie = TieIndicator()
            attach(tie, result_leaves[-1])
        assert isinstance(result_leaves, Selection)
        assert all(isinstance(_, Leaf) for _ in result_leaves)
        return result_leaves
Ejemplo n.º 6
0
    def __init__(
        self,
        *arguments,
        multiplier: typings.DurationTyping = None,
        tag: Tag = None,
    ) -> None:
        from abjad.ly import drums
        from .Chord import Chord

        assert len(arguments) in (0, 1, 2)
        if len(arguments) == 1 and isinstance(arguments[0], str):
            string = f"{{ {arguments[0]} }}"
            parsed = parse(string)
            assert len(parsed) == 1 and isinstance(parsed[0], Leaf)
            arguments = tuple([parsed[0]])
        written_pitch = None
        is_cautionary = False
        is_forced = False
        is_parenthesized = False
        if len(arguments) == 1 and isinstance(arguments[0], Leaf):
            leaf = arguments[0]
            written_pitch = None
            written_duration = leaf.written_duration
            if multiplier is None:
                multiplier = leaf.multiplier
            if isinstance(leaf, Note) and leaf.note_head is not None:
                written_pitch = leaf.note_head.written_pitch
                is_cautionary = leaf.note_head.is_cautionary
                is_forced = leaf.note_head.is_forced
                is_parenthesized = leaf.note_head.is_parenthesized
            # TODO: move into separate from_chord() constructor:
            elif isinstance(leaf, Chord):
                written_pitches = [x.written_pitch for x in leaf.note_heads]
                if written_pitches:
                    written_pitch = written_pitches[0]
                    is_cautionary = leaf.note_heads[0].is_cautionary
                    is_forced = leaf.note_heads[0].is_forced
                    is_parenthesized = leaf.note_heads[0].is_parenthesized
        elif len(arguments) == 2:
            written_pitch, written_duration = arguments
        elif len(arguments) == 0:
            written_pitch = NamedPitch("C4")
            written_duration = Duration(1, 4)
        else:
            raise ValueError("can not initialize note from {arguments!r}.")
        Leaf.__init__(self, written_duration, multiplier=multiplier, tag=tag)
        if written_pitch is not None:
            if written_pitch not in drums:
                self.note_head = NoteHead(
                    written_pitch=written_pitch,
                    is_cautionary=is_cautionary,
                    is_forced=is_forced,
                    is_parenthesized=is_parenthesized,
                )
            else:
                assert isinstance(written_pitch, str), repr(written_pitch)
                self.note_head = DrumNoteHead(
                    written_pitch=written_pitch,
                    is_cautionary=is_cautionary,
                    is_forced=is_forced,
                    is_parenthesized=is_parenthesized,
                )
        else:
            self._note_head = None
        if len(arguments) == 1 and isinstance(arguments[0], Leaf):
            self._copy_override_and_set_from_leaf(arguments[0])
Ejemplo n.º 7
0
 def __init__(
     self,
     *arguments,
     multiplier: typings.DurationTyping = None,
     tag: str = None,
 ) -> None:
     from abjad.ly import drums
     assert len(arguments) in (0, 1, 2)
     if len(arguments) == 1 and isinstance(arguments[0], str):
         string = f'{{ {arguments[0]} }}'
         parsed = parse(string)
         assert len(parsed) == 1 and isinstance(parsed[0], Leaf)
         arguments = tuple([parsed[0]])
     is_cautionary = False
     is_forced = False
     is_parenthesized = False
     if len(arguments) == 1 and isinstance(arguments[0], Leaf):
         leaf = arguments[0]
         written_pitch = None
         written_duration = leaf.written_duration
         if multiplier is None:
             multiplier = leaf.multiplier
         if 'written_pitch' in dir(leaf):
             written_pitch = leaf.note_head.written_pitch
             is_cautionary = leaf.note_head.is_cautionary
             is_forced = leaf.note_head.is_forced
             is_parenthesized = leaf.note_head.is_parenthesized
         elif 'written_pitches' in dir(leaf):
             written_pitches = [x.written_pitch for x in leaf.note_heads]
             if written_pitches:
                 written_pitch = written_pitches[0]
                 is_cautionary = leaf.note_heads[0].is_cautionary
                 is_forced = leaf.note_heads[0].is_forced
                 is_parenthesized = leaf.note_heads[0].is_parenthesized
     elif len(arguments) == 2:
         written_pitch, written_duration = arguments
     elif len(arguments) == 0:
         written_pitch = 'C4'
         written_duration = Duration(1, 4)
     else:
         raise ValueError('can not initialize note from {arguments!r}.')
     Leaf.__init__(
         self,
         written_duration,
         multiplier=multiplier,
         tag=tag,
     )
     if written_pitch is not None:
         if written_pitch not in drums:
             self.note_head = NoteHead(
                 written_pitch=written_pitch,
                 is_cautionary=is_cautionary,
                 is_forced=is_forced,
                 is_parenthesized=is_parenthesized,
             )
         else:
             self.note_head = DrumNoteHead(
                 written_pitch=written_pitch,
                 is_cautionary=is_cautionary,
                 is_forced=is_forced,
                 is_parenthesized=is_parenthesized,
             )
     else:
         self._note_head = None
     if len(arguments) == 1 and isinstance(arguments[0], Leaf):
         self._copy_override_and_set_from_leaf(arguments[0])
Ejemplo n.º 8
0
    def __add__(self, argument) -> typing.Optional["MetronomeMark"]:
        """
        Adds metronome mark to ``argument``.

        ..  container:: example

            Adds one metronome mark to another:

            >>> mark_1 = abjad.MetronomeMark((1, 4), 60)
            >>> mark_2 = abjad.MetronomeMark((1, 4), 90)
            >>> mark_1 + mark_2
            MetronomeMark(reference_duration=Duration(1, 4), units_per_minute=150)

            >>> mark_2 + mark_1
            MetronomeMark(reference_duration=Duration(1, 4), units_per_minute=150)

        ..  container:: example exception

            Raises imprecise metronome mark error with textual indication:

            >>> mark_1 = abjad.MetronomeMark(textual_indication='Langsam')
            >>> mark_2 = abjad.MetronomeMark((1, 4), 90)
            >>> mark_1 + mark_2
            Traceback (most recent call last):
                ...
            abjad.exceptions.ImpreciseMetronomeMarkError

        ..  container:: example exception

            Raises imprecise metronome mark error with range:

            >>> mark_1 = abjad.MetronomeMark((1, 8), (90, 92))
            >>> mark_2 = abjad.MetronomeMark((1, 4), 90)
            >>> mark_1 + mark_2
            Traceback (most recent call last):
                ...
            abjad.exceptions.ImpreciseMetronomeMarkError

        ..  container:: example exception

            Raises type error when ``argument`` is not a metronome mark:

            >>> abjad.MetronomeMark((1, 4), 60) + 90
            Traceback (most recent call last):
                ...
            TypeError: 90

        """
        if not isinstance(argument, type(self)):
            raise TypeError(argument)
        if self.is_imprecise or argument.is_imprecise:
            raise exceptions.ImpreciseMetronomeMarkError
        assert isinstance(self.quarters_per_minute, Fraction)
        assert isinstance(argument.quarters_per_minute, Fraction)
        assert isinstance(self.reference_duration, Duration)
        assert isinstance(argument.reference_duration, Duration)
        new_quarters_per_minute = (
            self.quarters_per_minute + argument.quarters_per_minute
        )
        minimum_denominator = min(
            (
                self.reference_duration.denominator,
                argument.reference_duration.denominator,
            )
        )
        nonreduced_fraction = NonreducedFraction(new_quarters_per_minute / 4)
        nonreduced_fraction = nonreduced_fraction.with_denominator(minimum_denominator)
        (
            new_units_per_minute,
            new_reference_duration_denominator,
        ) = nonreduced_fraction.pair
        new_reference_duration = Duration(1, new_reference_duration_denominator)
        metronome_mark = type(self)(new_reference_duration, new_units_per_minute)
        return metronome_mark
Ejemplo n.º 9
0
    def __sub__(self, argument) -> "MetronomeMark":
        """
        Subtracts ``argument`` from metronome mark.

        ..  container:: example

            Same reference reference durations:

            >>> mark_1 = abjad.MetronomeMark((1, 4), 90)
            >>> mark_2 = abjad.MetronomeMark((1, 4), 60)
            >>> mark_1 - mark_2
            MetronomeMark(reference_duration=Duration(1, 4), units_per_minute=30)

        ..  container:: example

            Different reference durations:

            >>> mark_1 = abjad.MetronomeMark((1, 4), 90)
            >>> mark_2 = abjad.MetronomeMark((1, 2), 90)
            >>> mark_1 - mark_2
            MetronomeMark(reference_duration=Duration(1, 4), units_per_minute=45)

        ..  container:: example exception

            Raises imprecise metronome mark error with textual indication:

            >>> mark_1 = abjad.MetronomeMark(textual_indication='Langsam')
            >>> mark_2 = abjad.MetronomeMark((1, 2), 90)
            >>> mark_1 - mark_2
            Traceback (most recent call last):
                ...
            abjad.exceptions.ImpreciseMetronomeMarkError

        """
        if not isinstance(argument, type(self)):
            raise Exception("must be metronome mark: {argument!r}.")
        if self.is_imprecise or argument.is_imprecise:
            raise exceptions.ImpreciseMetronomeMarkError
        assert isinstance(self.quarters_per_minute, (int, float, Fraction))
        assert isinstance(argument.quarters_per_minute, (int, float, Fraction))
        assert isinstance(self.reference_duration, Duration)
        assert isinstance(argument.reference_duration, Duration)
        new_quarters_per_minute = (
            self.quarters_per_minute - argument.quarters_per_minute
        )
        minimum_denominator = min(
            (
                self.reference_duration.denominator,
                argument.reference_duration.denominator,
            )
        )
        nonreduced_fraction = NonreducedFraction(new_quarters_per_minute / 4)
        nonreduced_fraction = nonreduced_fraction.with_denominator(minimum_denominator)
        (
            new_units_per_minute,
            new_reference_duration_denominator,
        ) = nonreduced_fraction.pair
        new_reference_duration = Duration(1, new_reference_duration_denominator)
        metronome_mark = type(self)(
            reference_duration=new_reference_duration,
            units_per_minute=new_units_per_minute,
        )
        return metronome_mark
Ejemplo n.º 10
0
 def _make_tied_leaf(
     class_,
     duration,
     increase_monotonic=None,
     forbidden_duration=None,
     multiplier=None,
     pitches=None,
     tag=None,
     tie_parts=True,
     repeat_ties=False,
 ):
     from abjad.spanners import tie as abjad_tie
     duration = Duration(duration)
     if forbidden_duration is not None:
         assert forbidden_duration.is_assignable
         assert forbidden_duration.numerator == 1
     # find preferred numerator of written durations if necessary
     if (forbidden_duration is not None and forbidden_duration <= duration):
         denominators = [
             2 * forbidden_duration.denominator,
             duration.denominator,
         ]
         denominator = mathtools.least_common_multiple(*denominators)
         forbidden_duration = NonreducedFraction(forbidden_duration)
         forbidden_duration = forbidden_duration.with_denominator(
             denominator)
         duration = NonreducedFraction(duration)
         duration = duration.with_denominator(denominator)
         forbidden_numerator = forbidden_duration.numerator
         assert forbidden_numerator % 2 == 0
         preferred_numerator = forbidden_numerator / 2
     # make written duration numerators
     numerators = []
     parts = mathtools.partition_integer_into_canonic_parts(
         duration.numerator)
     if (forbidden_duration is not None and forbidden_duration <= duration):
         for part in parts:
             if forbidden_numerator <= part:
                 better_parts = LeafMaker._partition_less_than_double(
                     part,
                     preferred_numerator,
                 )
                 numerators.extend(better_parts)
             else:
                 numerators.append(part)
     else:
         numerators = parts
     # reverse numerators if necessary
     if increase_monotonic:
         numerators = list(reversed(numerators))
     # make one leaf per written duration
     result = []
     for numerator in numerators:
         written_duration = Duration(
             numerator,
             duration.denominator,
         )
         if pitches is not None:
             arguments = (pitches, written_duration)
         else:
             arguments = (written_duration, )
         result.append(class_(*arguments, multiplier=multiplier, tag=tag))
     result = Selection(result)
     # tie if required
     if tie_parts and 1 < len(result):
         if not issubclass(class_, (Rest, Skip)):
             abjad_tie(result, repeat=repeat_ties)
     return result
Ejemplo n.º 11
0
    def make_tempo_equation_markup(
        reference_duration, units_per_minute, *, decimal=None
    ) -> Markup:
        r"""
        Makes tempo equation markup.

        ..  container:: example

            Integer-valued metronome mark:

            >>> markup = abjad.MetronomeMark.make_tempo_equation_markup(
            ...     (1, 4),
            ...     90,
            ...  )
            >>> abjad.show(markup) # doctest: +SKIP

            ..  docs::

                >>> print(format(markup))
                \markup \abjad-metronome-mark-markup #2 #0 #1 #"90"

        ..  container:: example

            Float-valued metronome mark:

            >>> markup = abjad.MetronomeMark.make_tempo_equation_markup(
            ...     (1, 4),
            ...     90.1,
            ... )
            >>> abjad.show(markup) # doctest: +SKIP

            ..  docs::

                >>> print(format(markup))
                \markup \abjad-metronome-mark-markup #2 #0 #1 #"90.1"

        ..  container:: example

            Rational-valued metronome mark:

            >>> markup = abjad.MetronomeMark.make_tempo_equation_markup(
            ...     abjad.Duration(1, 4),
            ...     abjad.Fraction(272, 3),
            ... )
            >>> abjad.show(markup) # doctest: +SKIP

            ..  docs::

                >>> print(format(markup))
                \markup \abjad-metronome-mark-mixed-number-markup #2 #0 #1 #"90" #"2" #"3"

        """
        reference_duration_ = Duration(reference_duration)
        log = reference_duration_.exponent
        dots = reference_duration_.dot_count
        stem = 1
        if isinstance(
            units_per_minute, Fraction
        ) and not mathtools.is_integer_equivalent_number(units_per_minute):
            if decimal:
                decimal_: typing.Union[float, str]
                if decimal is True:
                    decimal_ = float(units_per_minute)
                else:
                    assert isinstance(decimal, str), repr(decimal)
                    decimal_ = decimal
                markup = Markup(
                    r"\markup \abjad-metronome-mark-markup"
                    f' #{log} #{dots} #{stem} #"{decimal_}"',
                    literal=True,
                )
            else:
                nonreduced = NonreducedFraction(units_per_minute)
                base = int(nonreduced)
                remainder = nonreduced - base
                n, d = remainder.pair
                markup = Markup(
                    r"\markup \abjad-metronome-mark-mixed-number-markup"
                    f" #{log} #{dots} #{stem}"
                    f' #"{base}" #"{n}" #"{d}"',
                    literal=True,
                )
        else:
            markup = Markup(
                r"\markup \abjad-metronome-mark-markup"
                f' #{log} #{dots} #{stem} #"{units_per_minute}"',
                literal=True,
            )
        return markup
Ejemplo n.º 12
0
    def __call__(self, pitches, durations) -> Selection:
        """
        Calls leaf-maker on ``pitches`` and ``durations``.

        Returns selection.
        """
        from .Tuplet import Tuplet
        if isinstance(pitches, str):
            pitches = pitches.split()
        if not isinstance(pitches, collections.Iterable):
            pitches = [pitches]
        if isinstance(durations, (numbers.Number, tuple)):
            durations = [durations]
        nonreduced_fractions = Sequence(
            [NonreducedFraction(_) for _ in durations])
        size = max(len(nonreduced_fractions), len(pitches))
        nonreduced_fractions = nonreduced_fractions.repeat_to_length(size)
        pitches = Sequence(pitches).repeat_to_length(size)
        duration_groups = Duration._group_by_implied_prolation(
            nonreduced_fractions)
        result: typing.List[typing.Union[Tuplet, Leaf]] = []
        for duration_group in duration_groups:
            # get factors in denominator of duration group other than 1, 2.
            factors = mathtools.factors(duration_group[0].denominator)
            factors = set(factors)
            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 = self._make_leaf_on_pitch(
                        pitch,
                        duration,
                        increase_monotonic=self.increase_monotonic,
                        forbidden_note_duration=self.forbidden_note_duration,
                        forbidden_rest_duration=self.forbidden_rest_duration,
                        repeat_ties=self.repeat_ties,
                        skips_instead_of_rests=self.skips_instead_of_rests,
                        tag=self.tag,
                        use_multimeasure_rests=self.use_multimeasure_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 / Duration(*multiplier)
                duration_group = [
                    ratio * Duration(duration) for duration in duration_group
                ]
                # make tuplet leaves
                tuplet_leaves: typing.List[Leaf] = []
                for pitch, duration in zip(current_pitches, duration_group):
                    leaves = self._make_leaf_on_pitch(
                        pitch,
                        duration,
                        increase_monotonic=self.increase_monotonic,
                        repeat_ties=self.repeat_ties,
                        skips_instead_of_rests=self.skips_instead_of_rests,
                        tag=self.tag,
                        use_multimeasure_rests=self.use_multimeasure_rests,
                    )
                    tuplet_leaves.extend(leaves)
                tuplet = Tuplet(multiplier, tuplet_leaves)
                result.append(tuplet)
        return Selection(result)
Ejemplo n.º 13
0
    def check_beamed_long_notes(self,
                                argument=None
                                ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks beamed long notes.

        ..  container:: example

            Beamed quarter notes are not wellformed:

            >>> voice = abjad.Voice("c'4 d'4 e'4 f'4")
            >>> abjad.attach(abjad.StartBeam(), voice[0])
            >>> abjad.attach(abjad.StopBeam(), voice[1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'4
                    [
                    d'4
                    ]
                    e'4
                    f'4
                }

            >>> agent = abjad.inspect(voice)
            >>> print(agent.tabulate_wellformedness())
            2 /	4 beamed long notes
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	5 missing parents
            0 /	4 notes on wrong clef
            0 /	4 out of range pitches
            0 /	0 overlapping text spanners
            0 /	0 unmatched stop text spans
            0 /	0 unterminated hairpins
            0 /	0 unterminated text spanners

            Beamed eighth notes are wellformed:

            >>> voice = abjad.Voice("c'8 d'8 e'8 f'8")
            >>> abjad.attach(abjad.StartBeam(), voice[0])
            >>> abjad.attach(abjad.StopBeam(), voice[1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'8
                    [
                    d'8
                    ]
                    e'8
                    f'8
                }

            >>> agent = abjad.inspect(voice)
            >>> print(agent.tabulate_wellformedness())
            0 /	4 beamed long notes
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	5 missing parents
            0 /	4 notes on wrong clef
            0 /	4 out of range pitches
            0 /	0 overlapping text spanners
            0 /	0 unmatched stop text spans
            0 /	0 unterminated hairpins
            0 /	0 unterminated text spanners

        ..  container:: example

            REGRESSION. Matching start- and stop-beam indicators work
            correctly:

            >>> voice = abjad.Voice("c'8 d'8 e'4 f'2")
            >>> abjad.attach(abjad.StartBeam(), voice[0])
            >>> abjad.attach(abjad.StopBeam(), voice[1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'8
                    [
                    d'8
                    ]
                    e'4
                    f'2
                }

            >>> agent = abjad.inspect(voice)
            >>> print(agent.tabulate_wellformedness())
            0 /	4 beamed long notes
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	5 missing parents
            0 /	4 notes on wrong clef
            0 /	4 out of range pitches
            0 /	0 overlapping text spanners
            0 /	0 unmatched stop text spans
            0 /	0 unterminated hairpins
            0 /	0 unterminated text spanners

        The examples above feature Abjad voice containers because beams are
        voice-persistent.
        """
        violators, total = [], 0
        for leaf in iterate(argument).leaves():
            total += 1
            if leaf.written_duration < Duration((1, 4)):
                continue
            start_wrapper = inspect(leaf).effective_wrapper(StartBeam)
            if start_wrapper is None:
                continue
            stop_wrapper = inspect(leaf).effective_wrapper(StopBeam)
            if stop_wrapper is None:
                violators.append(leaf)
                continue
            if stop_wrapper.leaked_start_offset < start_wrapper.leaked_start_offset:
                violators.append(leaf)
                continue
            leaf_start_offset = inspect(leaf).timespan().start_offset
            if stop_wrapper.leaked_start_offset == leaf_start_offset:
                violators.append(leaf)
        return violators, total
Ejemplo n.º 14
0
    def __illustrate__(self):
        r"""
        Illustrates pitch set.

        ..  container:: example

            Treble and bass pitches:

            >>> set_ = abjad.PitchSet(
            ...     items=[-2, -1.5, 6, 7, -1.5, 7],
            ...     item_class=abjad.NumberedPitch,
            ...     )

            >>> abjad.show(set_) # doctest: +SKIP

            ..  docs::

                >>> lilypond_file = set_.__illustrate__()
                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new PianoStaff
                    <<
                        \new Staff
                        {
                            \new Voice
                            {
                                <fs' g'>1
                            }
                        }
                        \new Staff
                        {
                            \new Voice
                            {
                                <bf bqf>1
                            }
                        }
                    >>
                >>

        ..  container:: example

            Treble pitches only:

            >>> set_ = abjad.PitchSet(
            ...     items=[6, 7, 7],
            ...     item_class=abjad.NumberedPitch,
            ...     )

            >>> abjad.show(set_) # doctest: +SKIP

            ..  docs::

                >>> lilypond_file = set_.__illustrate__()
                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new PianoStaff
                    <<
                        \new Staff
                        {
                            \new Voice
                            {
                                <fs' g'>1
                            }
                        }
                        \new Staff
                        {
                            \new Voice
                            {
                                s1
                            }
                        }
                    >>
                >>

        Returns LilyPond file.
        """
        import abjad

        upper, lower = [], []
        for pitch in self:
            if pitch < 0:
                lower.append(pitch)
            else:
                upper.append(pitch)
        if upper:
            upper = abjad.Chord(upper, Duration(1))
        else:
            upper = abjad.Skip((1, 1))
        if lower:
            lower = abjad.Chord(lower, Duration(1))
        else:
            lower = abjad.Skip((1, 1))
        upper_voice = abjad.Voice([upper])
        upper_staff = abjad.Staff([upper_voice])
        lower_voice = abjad.Voice([lower])
        lower_staff = abjad.Staff([lower_voice])
        staff_group = abjad.StaffGroup([upper_staff, lower_staff],
                                       lilypond_type="PianoStaff")
        score = abjad.Score([staff_group])
        lilypond_file = abjad.LilyPondFile.new(score)
        return lilypond_file
Ejemplo n.º 15
0
    def to_tuplet(self, proportions):
        r"""
        Changes logical tie to tuplet.

        ..  container:: example

            >>> staff = abjad.Staff(r"df'8 c'8 ~ c'16 cqs''4")
            >>> abjad.attach(abjad.Dynamic('p'), staff[0])
            >>> abjad.attach(abjad.HairpinIndicator('<'), staff[0])
            >>> abjad.attach(abjad.Dynamic('f'), staff[-1])
            >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3
            >>> time_signature = abjad.TimeSignature((9, 16))
            >>> abjad.attach(time_signature, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                \with
                {
                    \override DynamicLineSpanner.staff-padding = #3
                }
                {
                    \time 9/16
                    df'8
                    \p
                    \<
                    c'8
                    ~
                    c'16
                    cqs''4
                    \f
                }

            >>> logical_tie = abjad.inspect(staff[1]).logical_tie()
            >>> logical_tie.to_tuplet([2, 1, 1, 1])
            Tuplet(Multiplier(3, 5), "c'8 c'16 c'16 c'16")

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                \with
                {
                    \override DynamicLineSpanner.staff-padding = #3
                }
                {
                    \time 9/16
                    df'8
                    \p
                    \<
                    \tweak text #tuplet-number::calc-fraction-text
                    \times 3/5 {
                        c'8
                        c'16
                        c'16
                        c'16
                    }
                    cqs''4
                    \f
                }

            >>> abjad.show(staff) # doctest: +SKIP

        ..  container:: example

            >>> staff = abjad.Staff(r"c'8 ~ c'16 cqs''4")
            >>> abjad.hairpin('p < f', staff[:])
            >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3
            >>> time_signature = abjad.TimeSignature((7, 16))
            >>> abjad.attach(time_signature, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                \with
                {
                    \override DynamicLineSpanner.staff-padding = #3
                }
                {
                    \time 7/16
                    c'8
                    \p
                    \<
                    ~
                    c'16
                    cqs''4
                    \f
                }

        Returns tuplet.
        """
        from .Note import Note
        from .Note import Note
        from .NoteMaker import NoteMaker
        from .Tuplet import Tuplet
        proportions = Ratio(proportions)
        target_duration = self._get_preprolated_duration()
        prolated_duration = target_duration / sum(proportions.numbers)
        basic_written_duration = \
            prolated_duration.equal_or_greater_power_of_two
        written_durations = [
            _ * basic_written_duration for _ in proportions.numbers
            ]
        maker = NoteMaker()
        try:
            notes = [Note(0, _) for _ in written_durations]
        except exceptions.AssignabilityError:
            denominator = target_duration._denominator
            note_durations = [
                Duration(_, denominator)
                for _ in proportions.numbers
                ]
            notes = maker(0, note_durations)
        tuplet = Tuplet.from_duration(target_duration, notes)
        for leaf in self:
            detach(TieIndicator, leaf)
            detach(RepeatTie, leaf)
        mutate(self).replace(tuplet)
        return tuplet
Ejemplo n.º 16
0
 def __init__(
     self,
     *arguments,
     multiplier: typings.DurationTyping = None,
     tag: str = None,
 ) -> None:
     from abjad.ly import drums
     assert len(arguments) in (0, 1, 2)
     self._note_heads = NoteHeadList(client=self)
     if len(arguments) == 1 and isinstance(arguments[0], str):
         string = f'{{ {arguments[0]} }}'
         parsed = parse(string)
         assert len(parsed) == 1 and isinstance(parsed[0], Leaf)
         arguments = tuple([parsed[0]])
     are_cautionary: typing.List[typing.Optional[bool]] = []
     are_forced: typing.List[typing.Optional[bool]] = []
     are_parenthesized: typing.List[typing.Optional[bool]] = []
     if len(arguments) == 1 and isinstance(arguments[0], Leaf):
         leaf = arguments[0]
         written_pitches = []
         written_duration = leaf.written_duration
         if multiplier is None:
             multiplier = leaf.multiplier
         if 'written_pitch' in dir(leaf):
             written_pitches.append(leaf.note_head.written_pitch)
             are_cautionary = [leaf.note_head.is_cautionary]
             are_forced = [leaf.note_head.is_forced]
             are_parenthesized = [leaf.note_head.is_parenthesized]
         elif 'written_pitches' in dir(leaf):
             written_pitches.extend(x.written_pitch
                                    for x in leaf.note_heads)
             are_cautionary = [x.is_cautionary for x in leaf.note_heads]
             are_forced = [x.is_forced for x in leaf.note_heads]
             are_parenthesized = [
                 x.is_parenthesized for x in leaf.note_heads
             ]
     elif len(arguments) == 2:
         written_pitches, written_duration = arguments
         if isinstance(written_pitches, str):
             written_pitches = [x for x in written_pitches.split() if x]
         elif isinstance(written_pitches, type(self)):
             written_pitches = written_pitches.written_pitches
     elif len(arguments) == 0:
         written_pitches = [0, 4, 7]
         written_duration = Duration(1, 4)
     else:
         raise ValueError(f'can not initialize chord from {arguments!r}.')
     Leaf.__init__(
         self,
         written_duration,
         multiplier=multiplier,
         tag=tag,
     )
     if not are_cautionary:
         are_cautionary = [None] * len(written_pitches)
     if not are_forced:
         are_forced = [None] * len(written_pitches)
     if not are_parenthesized:
         are_parenthesized = [None] * len(written_pitches)
     for written_pitch, is_cautionary, is_forced, is_parenthesized in zip(
             written_pitches, are_cautionary, are_forced,
             are_parenthesized):
         if not is_cautionary:
             is_cautionary = None
         if not is_forced:
             is_forced = None
         if not is_parenthesized:
             is_parenthesized = None
         if written_pitch not in drums:
             note_head = NoteHead(
                 written_pitch=written_pitch,
                 is_cautionary=is_cautionary,
                 is_forced=is_forced,
                 is_parenthesized=is_parenthesized,
             )
         else:
             note_head = DrumNoteHead(
                 written_pitch=written_pitch,
                 is_cautionary=is_cautionary,
                 is_forced=is_forced,
                 is_parenthesized=is_parenthesized,
             )
         self._note_heads.append(note_head)
     if len(arguments) == 1 and isinstance(arguments[0], Leaf):
         self._copy_override_and_set_from_leaf(arguments[0])
Ejemplo n.º 17
0
 def _split_by_duration(
     self,
     duration,
     tie_split_notes=True,
     repeat_ties=False,
     ):
     if self.is_simultaneous:
         return self._split_simultaneous_by_duration(
             duration=duration,
             tie_split_notes=tie_split_notes,
             repeat_ties=repeat_ties,
             )
     duration = Duration(duration)
     assert 0 <= duration, repr(duration)
     if duration == 0:
         return [], self
     # get split point score offset
     timespan = inspect(self).timespan()
     global_split_point = timespan.start_offset + duration
     # get any duration-crossing descendents
     cross_offset = timespan.start_offset + duration
     duration_crossing_descendants = []
     for descendant in inspect(self).descendants():
         timespan = inspect(descendant).timespan()
         start_offset = timespan.start_offset
         stop_offset = timespan.stop_offset
         if start_offset < cross_offset < stop_offset:
             duration_crossing_descendants.append(descendant)
     # any duration-crossing leaf will be at end of list
     bottom = duration_crossing_descendants[-1]
     did_split_leaf = False
     # if split point necessitates leaf split
     if isinstance(bottom, Leaf):
         assert isinstance(bottom, Leaf)
         did_split_leaf = True
         timespan = inspect(bottom).timespan()
         start_offset = timespan.start_offset
         split_point_in_bottom = global_split_point - start_offset
         new_leaves = bottom._split_by_durations(
             [split_point_in_bottom],
             tie_split_notes=tie_split_notes,
             repeat_ties=repeat_ties,
             )
         for leaf in new_leaves:
             timespan = inspect(leaf).timespan()
             if timespan.stop_offset == global_split_point:
                 leaf_left_of_split = leaf
             if timespan.start_offset == global_split_point:
                 leaf_right_of_split = leaf
         duration_crossing_containers = duration_crossing_descendants[:-1]
         if not len(duration_crossing_containers):
             return left_list, right_list
     # if split point falls between leaves
     # then find leaf to immediate right of split point
     # in order to start upward crawl through duration-crossing containers
     else:
         duration_crossing_containers = duration_crossing_descendants[:]
         for leaf in iterate(bottom).leaves():
             timespan = inspect(leaf).timespan()
             if timespan.start_offset == global_split_point:
                 leaf_right_of_split = leaf
                 leaf_left_of_split = inspect(leaf).leaf(-1)
                 break
         else:
             raise Exception('can not split empty container {bottom!r}.')
     assert leaf_left_of_split is not None
     assert leaf_right_of_split is not None
     # find component to right of split
     # that is also immediate child of last duration-crossing container
     for component in inspect(leaf_right_of_split).parentage():
         parent = inspect(component).parentage().parent
         if parent is duration_crossing_containers[-1]:
             highest_level_component_right_of_split = component
             break
     else:
         raise ValueError('should not be able to get here.')
     # crawl back up through duration-crossing containers and split each
     previous = highest_level_component_right_of_split
     for container in reversed(duration_crossing_containers):
         assert isinstance(container, Container)
         index = container.index(previous)
         left, right = container._split_at_index(index)
         previous = right
     # reapply tie here if crawl above killed tie applied to leaves
     if did_split_leaf:
         if (
             tie_split_notes and
             isinstance(leaf_left_of_split, Note)
             ):
             if (
                 inspect(leaf_left_of_split).parentage().root is
                 inspect(leaf_right_of_split).parentage().root
                 ):
                 leaves_around_split = (
                     leaf_left_of_split,
                     leaf_right_of_split,
                     )
                 selection = select(leaves_around_split)
                 selection._attach_tie_to_leaves(repeat_ties=repeat_ties)
     # return list-wrapped halves of container
     return [left], [right]
Ejemplo n.º 18
0
    def _split_by_durations(self, durations, cyclic=False):
        from .Chord import Chord
        from .Note import Note
        from .Selection import Selection
        from .Tuplet import Tuplet

        durations = [Duration(_) for _ in durations]
        durations = Sequence(durations)
        leaf_duration = inspect(self).duration()
        if cyclic:
            durations = durations.repeat_to_weight(leaf_duration)
        if sum(durations) < leaf_duration:
            last_duration = leaf_duration - sum(durations)
            durations = list(durations)
            durations.append(last_duration)
            durations = Sequence(durations)
        durations = durations.truncate(weight=leaf_duration)
        originally_tied = inspect(self).has_indicator(Tie)
        originally_repeat_tied = inspect(self).has_indicator(RepeatTie)
        result_selections = []
        # detach grace containers
        before_grace_container = self._before_grace_container
        if before_grace_container is not None:
            detach(before_grace_container, self)
        after_grace_container = self._after_grace_container
        if after_grace_container is not None:
            detach(after_grace_container, self)
        # do other things
        leaf_prolation = inspect(self).parentage().prolation
        for duration in durations:
            new_leaf = copy.copy(self)
            preprolated_duration = duration / leaf_prolation
            selection = new_leaf._set_duration(preprolated_duration)
            result_selections.append(selection)
        result_components = Sequence(result_selections).flatten(depth=-1)
        result_components = select(result_components)
        result_leaves = select(result_components).leaves(grace=False)
        assert all(isinstance(_, Selection) for _ in result_selections)
        assert all(isinstance(_, Component) for _ in result_components)
        assert result_leaves.are_leaves()
        # strip result leaves of all indicators
        for leaf in result_leaves:
            detach(object, leaf)
        # replace leaf with flattened result
        if inspect(self).parentage().parent is not None:
            mutate(self).replace(result_components)
        # move indicators
        first_result_leaf = result_leaves[0]
        last_result_leaf = result_leaves[-1]
        for indicator in inspect(self).indicators():
            detach(indicator, self)
            direction = getattr(indicator, "_time_orientation", enums.Left)
            if direction is enums.Left:
                attach(indicator, first_result_leaf)
            elif direction == enums.Right:
                attach(indicator, last_result_leaf)
            else:
                raise ValueError(direction)
        # reattach grace containers
        if before_grace_container is not None:
            attach(before_grace_container, first_result_leaf)
        if after_grace_container is not None:
            attach(after_grace_container, last_result_leaf)
        # fuse tuplets
        if isinstance(result_components[0], Tuplet):
            mutate(result_components).fuse()
        # tie split notes
        if isinstance(self, (Note, Chord)) and 1 < len(result_leaves):
            result_leaves._attach_tie_to_leaves()
        if originally_repeat_tied and not inspect(
                result_leaves[0]).has_indicator(RepeatTie):
            attach(RepeatTie(), result_leaves[0])
        if originally_tied and not inspect(
                result_leaves[-1]).has_indicator(Tie):
            attach(Tie(), result_leaves[-1])
        assert isinstance(result_leaves, Selection)
        assert all(isinstance(_, Leaf) for _ in result_leaves)
        return result_leaves