Esempio n. 1
0
 def _add_container_identifiers(self):
     if self.environment == "docs" and not getattr(
         self, "test_container_identifiers", False
     ):
         return
     segment_name = self.segment_name or ""
     segment_name = String(segment_name).to_segment_lilypond_identifier()
     contexts = []
     try:
         context = self.score["Global_Skips"]
         contexts.append(context)
     except ValueError:
         pass
     try:
         context = self.score["Global_Rests"]
         contexts.append(context)
     except ValueError:
         pass
     for voice in iterate(self.score).components(Voice):
         if inspect(voice).annotation("INTERMITTENT") is True:
             continue
         contexts.append(voice)
     container_to_part_assignment = OrderedDict()
     for context in contexts:
         if segment_name:
             context_identifier = f"{segment_name}_{context.name}"
         else:
             context_identifier = context.name
         context.identifier = f"%*% {context_identifier}"
         part_container_count = 0
         for container in iterate(context).components(Container):
             if not container.identifier:
                 continue
             if container.identifier.startswith("%*% Part"):
                 part_container_count += 1
                 globals_ = globals()
                 part = container.identifier.strip("%*% ")
                 part = eval(part, globals_)
                 suffix = String().base_26(part_container_count).lower()
                 container_identifier = f"{context_identifier}_{suffix}"
                 container_identifier = String(container_identifier)
                 assert container_identifier.is_lilypond_identifier()
                 assert (
                     container_identifier
                     not in container_to_part_assignment
                 )
                 timespan = inspect(container).timespan()
                 pair = (part, timespan)
                 container_to_part_assignment[container_identifier] = pair
                 container.identifier = f"%*% {container_identifier}"
     for staff in iterate(self.score).components(Staff):
         if segment_name:
             context_identifier = f"{segment_name}_{staff.name}"
         else:
             context_identifier = staff.name
         staff.identifier = f"%*% {context_identifier}"
     self._container_to_part_assignment = container_to_part_assignment
Esempio n. 2
0
 def _add_container_identifiers(self):
     if (self.environment == 'docs'
             and not getattr(self, 'test_container_identifiers', False)):
         return
     segment_name = self.segment_name or ''
     segment_name = String(segment_name).to_segment_lilypond_identifier()
     contexts = []
     try:
         context = self.score['Global_Skips']
         contexts.append(context)
     except ValueError:
         pass
     try:
         context = self.score['Global_Rests']
         contexts.append(context)
     except ValueError:
         pass
     for voice in iterate(self.score).components(Voice):
         if inspect(voice).annotation('INTERMITTENT') is True:
             continue
         contexts.append(voice)
     container_to_part_assignment = OrderedDict()
     for context in contexts:
         if segment_name:
             context_identifier = f'{segment_name}_{context.name}'
         else:
             context_identifier = context.name
         context.identifier = f'%*% {context_identifier}'
         part_container_count = 0
         for container in iterate(context).components(Container):
             if not container.identifier:
                 continue
             if container.identifier.startswith('%*% Part'):
                 part_container_count += 1
                 globals_ = globals()
                 part = container.identifier.strip('%*% ')
                 part = eval(part, globals_)
                 suffix = String().base_26(part_container_count).lower()
                 container_identifier = f'{context_identifier}_{suffix}'
                 container_identifier = String(container_identifier)
                 assert container_identifier.is_lilypond_identifier()
                 assert container_identifier not in \
                     container_to_part_assignment
                 timespan = inspect(container).timespan()
                 pair = (part, timespan)
                 container_to_part_assignment[container_identifier] = pair
                 container.identifier = f'%*% {container_identifier}'
     for staff in iterate(self.score).components(Staff):
         if segment_name:
             context_identifier = f'{segment_name}_{staff.name}'
         else:
             context_identifier = staff.name
         staff.identifier = f'%*% {context_identifier}'
     self._container_to_part_assignment = container_to_part_assignment
Esempio n. 3
0
 def _update_all_leaf_indices_and_measure_numbers(score_root):
     """
     Call only when updating offsets.
     No separate state flags exist for leaf indices or measure numbers.
     """
     from abjad.core.Context import Context
     if isinstance(score_root, Context):
         contexts = iterate(score_root).components(Context)
         for context in contexts:
             for leaf_index, leaf in enumerate(iterate(context).leaves()):
                 leaf._leaf_index = leaf_index
     else:
         for leaf_index, leaf in enumerate(iterate(score_root).leaves()):
             leaf._leaf_index = leaf_index
Esempio n. 4
0
 def check_misrepresented_flags(
     self, argument=None
 ) -> typing.Tuple[typing.List, int]:
     """
     Checks misrepresented flags.
     """
     violators: typing.List[Leaf] = []
     total = set()
     for leaf in iterate(argument).leaves():
         total.add(leaf)
         flags = leaf.written_duration.flag_count
         left = getattr(setting(leaf), "stem_left_beam_count", None)
         right = getattr(setting(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, len(total)
Esempio n. 5
0
    def check_empty_containers(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks empty containers.

        ..  container:: example

            >>> staff = abjad.Staff("c'4 d' e' f'")
            >>> staff.append(abjad.Container())

            >>> abjad.f(staff)
            \new Staff
            {
                c'4
                d'4
                e'4
                f'4
                {
                }
            }

            >>> wellformedness = abjad.Wellformedness()
            >>> violators, total = wellformedness.check_empty_containers(staff)
            >>> violators
            [Container()]

        """
        violators, containers = [], set()
        for container in iterate(argument).components(Container):
            containers.add(container)
            if len(container) == 0:
                violators.append(container)
        return violators, len(containers)
Esempio n. 6
0
 def _get_duration_in_seconds(self):
     if self.simultaneous:
         return max([Duration(0)] + [x._get_duration(in_seconds=True) for x in self])
     else:
         duration = Duration(0)
         for leaf in iterate(self).leaves():
             duration += leaf._get_duration(in_seconds=True)
         return duration
Esempio n. 7
0
 def _get_duration_in_seconds(self):
     if self.is_simultaneous:
         return max(
             [Duration(0)]
             + [x._get_duration(in_seconds=True) for x in self]
         )
     else:
         duration = Duration(0)
         for leaf in iterate(self).leaves():
             duration += leaf._get_duration(in_seconds=True)
         return duration
Esempio n. 8
0
 def _aggregate_context_wrappers(self, argument):
     """
     Special_Voice may contain other instances of Special_Voice.
     This currently happens with OnBeatGraceContainer.
     This method aggregates all Special_Voice wrappers for checks.
     """
     name_to_wrappers: typing.Dict = {}
     for context in iterate(argument).components(Context):
         if context.name not in name_to_wrappers:
             name_to_wrappers[context.name] = []
         wrappers = context._dependent_wrappers[:]
         name_to_wrappers[context.name].extend(wrappers)
     return name_to_wrappers
Esempio n. 9
0
 def check_missing_parents(
     self, argument=None
 ) -> typing.Tuple[typing.List, int]:
     """
     Checks missing parents.
     """
     violators, total = [], set()
     components = iterate(argument).components()
     for i, component in enumerate(components):
         total.add(component)
         if 0 < i:
             parentage = inspect(component).parentage(grace_notes=True)
             if parentage.parent is None:
                 violators.append(component)
     return violators, len(total)
Esempio n. 10
0
 def check_duplicate_ids(
     self, argument=None
 ) -> typing.Tuple[typing.List, int]:
     """
     Checks duplicate IDs.
     """
     violators = []
     components = iterate(argument).components()
     total_ids = [id(_) for _ in components]
     unique_ids = Sequence(total_ids).remove_repeats()
     if len(unique_ids) < len(total_ids):
         for current_id in unique_ids:
             if 1 < total_ids.count(current_id):
                 violators.extend(
                     [_ for _ in components if id(_) == current_id]
                 )
     return violators, len(total_ids)
Esempio n. 11
0
 def __illustrate__(
     self, default_paper_size=None, global_staff_size=None, includes=None
 ):
     """
     Illustrates score template.
     """
     score: Score = self()
     for voice in iterate(score).components(Voice):
         skip = Skip(1, tag="abjad.ScoreTemplate.__illustrate__")
         voice.append(skip)
     self.attach_defaults(score)
     lilypond_file: LilyPondFile = score.__illustrate__()
     lilypond_file = new(
         lilypond_file,
         default_paper_size=default_paper_size,
         global_staff_size=global_staff_size,
         includes=includes,
     )
     return lilypond_file
Esempio n. 12
0
    def _set_item(self, i, argument):
        from .GraceContainer import GraceContainer

        argument_indicators = []
        for component in iterate(argument).components():
            wrappers = inspect(component).wrappers()
            argument_indicators.extend(wrappers)
        if isinstance(i, int):
            argument = [argument]
            if i < 0:
                i = len(self) + i
            i = slice(i, i + 1)
        prototype = (Component, Selection)
        assert all(isinstance(_, prototype) for _ in argument)
        new_argument = []
        for item in argument:
            if isinstance(item, Selection):
                new_argument.extend(item)
            else:
                new_argument.append(item)
        argument = new_argument
        assert all(isinstance(_, Component) for _ in argument)
        if any(isinstance(_, GraceContainer) for _ in argument):
            raise Exception("must attach grace container to note or chord.")
        if self._check_for_cycles(argument):
            raise exceptions.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_components = self[start:stop]
        del self[start:stop]
        self._components.__setitem__(slice(start, start), argument)
        for component in argument:
            component._set_parent(self)
        for indicator in argument_indicators:
            if hasattr(indicator, "_update_effective_context"):
                indicator._update_effective_context()
Esempio n. 13
0
 def __illustrate__(
     self, default_paper_size=None, global_staff_size=None, includes=None
 ):
     """
     Illustrates score template.
     """
     score: Score = self()
     for voice in iterate(score).components(Voice):
         skip = Skip(1, tag="abjad.ScoreTemplate.__illustrate__")
         voice.append(skip)
     self.attach_defaults(score)
     lilypond_file: LilyPondFile = score.__illustrate__()
     lilypond_file = new(
         lilypond_file,
         default_paper_size=default_paper_size,
         global_staff_size=global_staff_size,
         includes=includes,
     )
     return lilypond_file
Esempio n. 14
0
    def _set_item(self, i, argument):
        from .BeforeGraceContainer import BeforeGraceContainer

        argument_indicators = []
        for component in iterate(argument).components():
            wrappers = inspect(component).wrappers()
            argument_indicators.extend(wrappers)
        if isinstance(i, int):
            argument = [argument]
            if i < 0:
                i = len(self) + i
            i = slice(i, i + 1)
        prototype = (Component, Selection)
        assert all(isinstance(_, prototype) for _ in argument)
        new_argument = []
        for item in argument:
            if isinstance(item, Selection):
                new_argument.extend(item)
            else:
                new_argument.append(item)
        argument = new_argument
        assert all(isinstance(_, Component) for _ in argument)
        if any(isinstance(_, BeforeGraceContainer) for _ in argument):
            raise Exception("must attach grace container to note or chord.")
        if self._check_for_cycles(argument):
            raise exceptions.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))
        del self[start:stop]
        self._components.__setitem__(slice(start, start), argument)
        for component in argument:
            component._set_parent(self)
        for indicator in argument_indicators:
            if hasattr(indicator, "_update_effective_context"):
                indicator._update_effective_context()
Esempio n. 15
0
File: Clef.py Progetto: Abjad/abjad
    def from_selection(selection) -> "Clef":
        """
        Makes clef from ``selection``.

        ..  container:: example

            >>> maker = abjad.NoteMaker()
            >>> notes = maker(range(-12, -6), [(1, 4)])
            >>> staff = abjad.Staff(notes)
            >>> abjad.Clef.from_selection(staff)
            Clef('bass')

            Choses between treble and bass based on minimal number of ledger
            lines.

        """
        pitches = iterate(selection).pitches()
        diatonic_pitch_numbers = [
            pitch._get_diatonic_pitch_number() for pitch in pitches
        ]
        max_diatonic_pitch_number = max(diatonic_pitch_numbers)
        min_diatonic_pitch_number = min(diatonic_pitch_numbers)
        lowest_treble_line_pitch = NamedPitch("E4")
        lowest_treble_line_diatonic_pitch_number = (
            lowest_treble_line_pitch._get_diatonic_pitch_number()
        )
        candidate_steps_below_treble = (
            lowest_treble_line_diatonic_pitch_number
            - min_diatonic_pitch_number
        )
        highest_bass_line_pitch = NamedPitch("A3")
        highest_bass_line_diatonic_pitch_number = (
            highest_bass_line_pitch._get_diatonic_pitch_number()
        )
        candidate_steps_above_bass = (
            max_diatonic_pitch_number - highest_bass_line_diatonic_pitch_number
        )
        if candidate_steps_above_bass < candidate_steps_below_treble:
            return Clef("bass")
        else:
            return Clef("treble")
Esempio n. 16
0
File: Clef.py Progetto: cablew/abjad
    def from_selection(selection) -> "Clef":
        """
        Makes clef from ``selection``.

        ..  container:: example

            >>> maker = abjad.NoteMaker()
            >>> notes = maker(range(-12, -6), [(1, 4)])
            >>> staff = abjad.Staff(notes)
            >>> abjad.Clef.from_selection(staff)
            Clef('bass')

            Choses between treble and bass based on minimal number of ledger
            lines.

        """
        pitches = iterate(selection).pitches()
        diatonic_pitch_numbers = [
            pitch._get_diatonic_pitch_number() for pitch in pitches
        ]
        max_diatonic_pitch_number = max(diatonic_pitch_numbers)
        min_diatonic_pitch_number = min(diatonic_pitch_numbers)
        lowest_treble_line_pitch = NamedPitch("E4")
        lowest_treble_line_diatonic_pitch_number = (
            lowest_treble_line_pitch._get_diatonic_pitch_number()
        )
        candidate_steps_below_treble = (
            lowest_treble_line_diatonic_pitch_number
            - min_diatonic_pitch_number
        )
        highest_bass_line_pitch = NamedPitch("A3")
        highest_bass_line_diatonic_pitch_number = (
            highest_bass_line_pitch._get_diatonic_pitch_number()
        )
        candidate_steps_above_bass = (
            max_diatonic_pitch_number - highest_bass_line_diatonic_pitch_number
        )
        if candidate_steps_above_bass < candidate_steps_below_treble:
            return Clef("bass")
        else:
            return Clef("treble")
Esempio n. 17
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
Esempio n. 18
0
    def rhythm(
        class_,
        selections,
        divisions=None,
        attach_lilypond_voice_commands=None,
        implicit_scaling=None,
        pitched_staff=None,
        simultaneous_selections=None,
        time_signatures=None,
    ):
        r"""
        Makes rhythm-styled LilyPond file.

        ..  container:: example

            Makes rhythmic staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 3/4
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 1/4
                        s1 * 1/4
                    }
                    \new RhythmicStaff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Set time signatures explicitly:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     [(6, 8), (4, 8), (2, 8)],
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 6/8
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 2/8
                        s1 * 1/4
                    }
                    \new RhythmicStaff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Makes pitched staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     pitched_staff=True,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 3/4
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 1/4
                        s1 * 1/4
                    }
                    \new Staff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Makes simultaneous voices:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> for note in abjad.iterate(selections).components(abjad.Note):
            ...     note.written_pitch = abjad.NamedPitch("e'")
            ...
            >>> selection_1 = selections[0] + selections[1] + selections[2]
            >>> selections = [
            ...     maker(12 * [0], [(1, 16)]),
            ...     maker(16 * [0], [(1, 32)]),
            ...     maker(4 * [0], [(1, 16)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> selection_2 = selections[0] + selections[1] + selections[2]
            >>> selections = {
            ...     'Voice_1': selection_1,
            ...     'Voice_2': selection_2,
            ... }
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> voice_1 = lilypond_file['Voice_1']
            >>> literal = abjad.LilyPondLiteral(r'\voiceOne', "opening")
            >>> abjad.attach(literal, voice_1)
            >>> voice_2 = lilypond_file['Voice_2']
            >>> literal = abjad.LilyPondLiteral(r'\voiceTwo', "opening")
            >>> abjad.attach(literal, voice_2)
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        s1 * 3/4
                        s1 * 1/2
                        s1 * 1/4
                    }
                    \new Staff
                    <<
                        \context Voice = "Voice_1"
                        {
                            \voiceOne
                            e'8
                            [
                            e'8
                            e'8
                            e'8
                            e'8
                            e'8
                            ]
                            e'16
                            [
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            ]
                            e'8
                            [
                            e'8
                            ]
                        }
                        \context Voice = "Voice_2"
                        {
                            \voiceTwo
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                            c'32
                            [
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            ]
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            ]
                        }
                    >>
                >>

        Returns LilyPond file.
        """
        if isinstance(selections, list):
            for selection in selections:
                if not isinstance(selection, Selection):
                    raise TypeError(f"must be selection: {selection!r}.")
        elif isinstance(selections, dict):
            for selection in selections.values():
                if not isinstance(selection, Selection):
                    raise TypeError(f"must be selection: {selection!r}.")
        else:
            raise TypeError(f"must be list or dictionary: {selections!r}.")
        score = Score()
        lilypond_file = LilyPondFile.new(
            score, includes=["default.ily", "rhythm-maker-docs.ily"])
        if pitched_staff is None:
            if isinstance(selections, list):
                selections_ = selections
            elif isinstance(selections, dict):
                selections_ = selections.values()
            else:
                raise TypeError(selections)
            for note in iterate(selections_).leaves(Note):
                if note.written_pitch != NamedPitch("c'"):
                    pitched_staff = True
                    break
        if isinstance(selections, list):
            if divisions is None:
                duration = abjad_inspect(selections).duration()
                divisions = [duration]
            time_signatures = time_signatures or divisions
            time_signatures = [TimeSignature(_) for _ in time_signatures]
            if pitched_staff:
                staff = Staff()
            else:
                staff = Staff(lilypond_type="RhythmicStaff")
            staff.extend(selections)
        elif isinstance(selections, dict):
            voices = []
            for voice_name in sorted(selections):
                selections_ = selections[voice_name]
                selections_ = sequence(selections_).flatten(depth=-1)
                selections_ = copy.deepcopy(selections_)
                voice = Voice(selections_, name=voice_name)
                if attach_lilypond_voice_commands:
                    voice_name_to_command_string = {
                        "Voice_1": "voiceOne",
                        "Voice_2": "voiceTwo",
                        "Voice_3": "voiceThree",
                        "Voice_4": "voiceFour",
                    }
                    command_string = voice_name_to_command_string.get(
                        voice_name)
                    if command_string:
                        command = LilyPondLiteral("\\" + command_string)
                        attach(command, voice)
                voices.append(voice)
            staff = Staff(voices, is_simultaneous=True)
            if divisions is None:
                duration = abjad_inspect(staff).duration()
                divisions = [duration]
        else:
            message = "must be list or dictionary of selections:"
            message += f" {selections!r}."
            raise TypeError(message)
        score.append(staff)
        assert isinstance(divisions, collections.abc.Sequence), repr(divisions)
        time_signatures = time_signatures or divisions
        context = Context(lilypond_type="GlobalContext")
        skips = []
        for time_signature in time_signatures:
            skip = Skip(1)
            skip.multiplier = time_signature
            attach(time_signature, skip, context="Score")
            skips.append(skip)
        context.extend(skips)
        score.insert(0, context)
        return lilypond_file
Esempio n. 19
0
    def check_unterminated_text_spanners(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks unterminated text spanners.

        ..  container:: example

            Unterminated text spanner is not wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> start_text_span = abjad.StartTextSpan()
            >>> abjad.attach(start_text_span, voice[0])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \startTextSpan
                c'4
                c'4
                c'4
            }

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

            Terminated text span is wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> start_text_span = abjad.StartTextSpan()
            >>> abjad.attach(start_text_span, voice[0])
            >>> stop_text_span = abjad.StopTextSpan()
            >>> abjad.attach(stop_text_span, voice[-1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'4
                    \startTextSpan
                    c'4
                    c'4
                    c'4
                    \stopTextSpan
                }

            >>> abjad.inspect(voice).wellformed()
            True

        """
        violators, total = [], 0
        for context in iterate(argument).components(Context):
            wrappers = context._dependent_wrappers[:]
            wrappers.sort(key=lambda _: _.start_offset)
            open_spanners: typing.Dict = {}
            for wrapper in wrappers:
                if isinstance(wrapper.indicator, StartTextSpan):
                    total += 1
                    command = wrapper.indicator.command
                    command = command.replace("start", "")
                    command = command.replace("Start", "")
                    if command not in open_spanners:
                        open_spanners[command] = []
                    open_spanners[command].append(wrapper.component)
                elif isinstance(wrapper.indicator, StopTextSpan):
                    command = wrapper.indicator.command
                    command = command.replace("stop", "")
                    command = command.replace("Stop", "")
                    if (
                        command not in open_spanners
                        or not open_spanners[command]
                    ):
                        # unmatched stop text span
                        pass
                    else:
                        open_spanners[command].pop()
            for command, list_ in open_spanners.items():
                for component in list_:
                    violators.append(component)
        return violators, total
Esempio n. 20
0
    def check_unterminated_hairpins(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks unterminated hairpins.

        ..  container:: example

            Unterminated crescendo is not wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> start_hairpin = abjad.StartHairpin('<')
            >>> abjad.attach(start_hairpin, voice[0])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \<
                c'4
                c'4
                c'4
            }

            >>> agent = abjad.inspect(voice)
            >>> print(agent.tabulate_wellformedness())
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            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
            1 /	1 unterminated hairpins
            0 /	0 unterminated text spanners

            Even with start dynamic:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> dynamic = abjad.Dynamic('f')
            >>> abjad.attach(dynamic, voice[0])
            >>> start_hairpin = abjad.StartHairpin('<')
            >>> abjad.attach(start_hairpin, voice[0])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \f
                \<
                c'4
                c'4
                c'4
            }

            >>> agent = abjad.inspect(voice)
            >>> print(agent.tabulate_wellformedness())
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            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
            1 /	1 unterminated hairpins
            0 /	0 unterminated text spanners

            Terminated crescendo is wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> start_hairpin = abjad.StartHairpin('<')
            >>> abjad.attach(start_hairpin, voice[0])
            >>> dynamic = abjad.Dynamic('f')
            >>> abjad.attach(dynamic, voice[-1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'4
                    \<
                    c'4
                    c'4
                    c'4
                    \f
                }

            >>> abjad.inspect(voice).wellformed()
            True

        ..  container:: example

            Bang-terminated crescendo is wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> start_hairpin = abjad.StartHairpin('<')
            >>> abjad.attach(start_hairpin, voice[0])
            >>> stop_hairpin = abjad.StopHairpin()
            >>> abjad.attach(stop_hairpin, voice[-1])
            >>> abjad.show(voice) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(voice)
                \new Voice
                {
                    c'4
                    \<
                    c'4
                    c'4
                    c'4
                    \!
                }

            >>> abjad.inspect(voice).wellformed()
            True

        """
        violators, total = [], 0
        for context in iterate(argument).components(Context):
            last_dynamic = None
            last_tag = None
            wrappers = context._dependent_wrappers[:]
            wrappers.sort(key=lambda _: _.start_offset)
            for wrapper in wrappers:
                parameter = getattr(wrapper.indicator, "parameter", None)
                if parameter == "DYNAMIC" or isinstance(
                    wrapper.indicator, StopHairpin
                ):
                    last_dynamic = wrapper.indicator
                    last_tag = wrapper.tag
                    if isinstance(wrapper.indicator, StartHairpin):
                        total += 1
            if isinstance(
                last_dynamic, StartHairpin
            ) and "right_broken" not in str(last_tag):
                violators.append(wrapper.component)
        return violators, total
Esempio n. 21
0
    def check_overlapping_text_spanners(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks overlapping text spanners.

        ..  container:: example

            Overlapping text spanners are not wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> abjad.text_spanner(voice)
            >>> abjad.text_spanner(voice[1:3])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \startTextSpan
                c'4
                \startTextSpan
                c'4
                \stopTextSpan
                c'4
                \stopTextSpan
            }

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

        ..  container:: example

            Overlapping text spanners with different IDs are wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> abjad.text_spanner(voice)
            >>> command = r'\startTextSpanOne'
            >>> start_text_span = abjad.StartTextSpan(command=command)
            >>> abjad.attach(start_text_span, voice[1])
            >>> command = r'\stopTextSpanOne'
            >>> stop_text_span = abjad.StopTextSpan(command=command)
            >>> abjad.attach(stop_text_span, voice[2])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \startTextSpan
                c'4
                \startTextSpanOne
                c'4
                \stopTextSpanOne
                c'4
                \stopTextSpan
            }

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

        ..  container:: example

            Enchained text spanners are wellformed:

            >>> voice = abjad.Voice("c'4 c'4 c'4 c'4")
            >>> abjad.text_spanner(voice[:3])
            >>> abjad.text_spanner(voice[-2:])
            >>> abjad.f(voice)
            \new Voice
            {
                c'4
                \startTextSpan
                c'4
                c'4
                \stopTextSpan
                \startTextSpan
                c'4
                \stopTextSpan
            }

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

        """
        violators, total = [], 0

        def key(wrapper):
            if isinstance(wrapper.indicator, StartTextSpan):
                priority = 1
            else:
                priority = 0
            return (wrapper.start_offset, priority)

        for context in iterate(argument).components(Context):
            wrappers = context._dependent_wrappers[:]
            wrappers.sort(key=key)
            open_spanners: typing.Dict = {}
            for wrapper in wrappers:
                if isinstance(wrapper.indicator, StartTextSpan):
                    # print(wrapper.indicator)
                    total += 1
                    command = wrapper.indicator.command
                    command = command.replace("start", "")
                    command = command.replace("Start", "")
                    # print(command, 'START', wrapper.start_offset)
                    if command not in open_spanners:
                        open_spanners[command] = []
                    if open_spanners[command]:
                        violators.append(wrapper.component)
                    open_spanners[command].append(wrapper.component)
                elif isinstance(wrapper.indicator, StopTextSpan):
                    # print(wrapper.indicator)
                    command = wrapper.indicator.command
                    command = command.replace("stop", "")
                    command = command.replace("Stop", "")
                    # print(command, 'STOP', wrapper.start_offset)
                    if command in open_spanners and open_spanners[command]:
                        open_spanners[command].pop()
        return violators, total
Esempio n. 22
0
    def check_out_of_range_pitches(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks out-of-range notes.

        ..  container:: example

            Out of range:

            >>> staff = abjad.Staff("c'8 r8 <d fs>8 r8")
            >>> violin = abjad.Violin()
            >>> abjad.attach(violin, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                {
                    c'8
                    r8
                    <d fs>8
                    r8
                }

            >>> agent = abjad.inspect(staff)
            >>> print(agent.tabulate_wellformedness())
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            0 /	5 missing parents
            0 /	4 notes on wrong clef
            1 /	2 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

            Allows out-of-range pitches:

            >>> staff = abjad.Staff("c'8 r8 <d fs>8 r8")
            >>> violin = abjad.Violin()
            >>> abjad.attach(violin, staff[0])
            >>> abjad.attach(abjad.const.ALLOW_OUT_OF_RANGE, staff[2])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                {
                    c'8
                    r8
                    <d fs>8
                    r8
                }

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

        """
        violators, total = [], set()
        for leaf in iterate(argument).leaves(pitched=True):
            total.add(leaf)
            if inspect(leaf).has_indicator(const.ALLOW_OUT_OF_RANGE):
                continue
            # TODO: change to has_indicator(const.HIDDEN):
            if inspect(leaf).annotation(const.HIDDEN) is True:
                continue
            instrument = inspect(leaf).effective(Instrument)
            if instrument is None:
                continue
            if leaf not in instrument.pitch_range:
                violators.append(leaf)
        return violators, len(total)
Esempio n. 23
0
    def check_notes_on_wrong_clef(
        self, argument=None
    ) -> typing.Tuple[typing.List, int]:
        r"""
        Checks notes and chords on wrong clef.

        ..  container:: example

            >>> staff = abjad.Staff("c'8 d'8 e'8 f'8")
            >>> clef = abjad.Clef('alto')
            >>> abjad.attach(clef, staff[0])
            >>> violin = abjad.Violin()
            >>> abjad.attach(violin, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                {
                    \clef "alto"
                    c'8
                    d'8
                    e'8
                    f'8
                }

            >>> agent = abjad.inspect(staff)
            >>> print(agent.tabulate_wellformedness())
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            0 /	5 missing parents
            4 /	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

            Allows percussion clef:

            >>> staff = abjad.Staff("c'8 d'8 e'8 f'8")
            >>> clef = abjad.Clef('percussion')
            >>> abjad.attach(clef, staff[0])
            >>> violin = abjad.Violin()
            >>> abjad.attach(violin, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(staff)
                \new Staff
                {
                    \clef "percussion"
                    c'8
                    d'8
                    e'8
                    f'8
                }

            >>> agent = abjad.inspect(staff)
            >>> print(agent.tabulate_wellformedness(allow_percussion_clef=True))
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            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

            Forbids percussion clef:

            >>> agent = abjad.inspect(staff)
            >>> print(agent.tabulate_wellformedness(allow_percussion_clef=False))
            0 /	5 duplicate ids
            0 /	1 empty containers
            0 /	4 misrepresented flags
            0 /	5 missing parents
            4 /	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

        """
        violators, total = [], set()
        for leaf in iterate(argument).leaves():
            total.add(leaf)
            instrument = inspect(leaf).effective(Instrument)
            if instrument is None:
                continue
            clef = inspect(leaf).effective(Clef)
            if clef is None:
                continue
            allowable_clefs = [Clef(_) for _ in instrument.allowable_clefs]
            if self.allow_percussion_clef:
                allowable_clefs.append(Clef("percussion"))
            if clef not in allowable_clefs:
                violators.append(leaf)
        return violators, len(total)
Esempio n. 24
0
 def _before_attach(self, argument):
     if self._ignore_before_attach:
         return
     for leaf in iterate(argument).leaves():
         detach(Tie, leaf)
Esempio n. 25
0
    def __getitem__(self, name):
        r"""
        Gets item with ``name``.

        ..  container:: example

            Gets header block:

            >>> lilypond_file = abjad.LilyPondFile.new()

            >>> lilypond_file['header']
            <Block(name='header')>

        ..  container:: example

            Searches score:

            >>> voice_1 = abjad.Voice("c''4 b' a' g'", name='Custom_Voice_1')
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceOne'), voice_1)
            >>> voice_2 = abjad.Voice("c'4 d' e' f'", name='Custom_Voice_2')
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceTwo'), voice_2)
            >>> staff = abjad.Staff(
            ...     [voice_1, voice_2],
            ...     is_simultaneous=True,
            ...     name='Custom_Staff',
            ...     )
            >>> score = abjad.Score([staff], name='Custom_Score')
            >>> lilypond_file = abjad.LilyPondFile.new(score)
            >>> abjad.show(score) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(score)
                \context Score = "Custom_Score"
                <<
                    \context Staff = "Custom_Staff"
                    <<
                        \context Voice = "Custom_Voice_1"
                        {
                            \voiceOne
                            c''4
                            b'4
                            a'4
                            g'4
                        }
                        \context Voice = "Custom_Voice_2"
                        {
                            \voiceTwo
                            c'4
                            d'4
                            e'4
                            f'4
                        }
                    >>
                >>

            >>> lilypond_file['score']
            <Block(name='score')>

            >>> lilypond_file['Custom_Score']
            <Score-"Custom_Score"<<1>>>

            >>> lilypond_file[abjad.Score]
            <Score-"Custom_Score"<<1>>>

            >>> lilypond_file['Custom_Staff']
            <Staff-"Custom_Staff"<<2>>>

            >>> lilypond_file[abjad.Staff]
            <Staff-"Custom_Staff"<<2>>>

            >>> lilypond_file['Custom_Voice_1']
            Voice("c''4 b'4 a'4 g'4", name='Custom_Voice_1')

            >>> lilypond_file['Custom_Voice_2']
            Voice("c'4 d'4 e'4 f'4", name='Custom_Voice_2')

            >>> lilypond_file[abjad.Voice]
            Voice("c''4 b'4 a'4 g'4", name='Custom_Voice_1')

        ..  container:: example

            REGRESSION. Works when score block contains parallel container:

                >>> include_container = abjad.Container()
                >>> string = r'\include "layout.ly"'
                >>> literal = abjad.LilyPondLiteral(string, 'opening')
                >>> abjad.attach(literal, include_container)
                >>> staff = abjad.Staff("c'4 d' e' f'", name='Custom_Staff')
                >>> container = abjad.Container(
                ...     [include_container, staff],
                ...     is_simultaneous=True,
                ...     )
                >>> lilypond_file = abjad.LilyPondFile.new(
                ...     container,
                ...     lilypond_language_token=False,
                ...     lilypond_version_token=False,
                ...     )
                >>> del(lilypond_file.items[:3])

                >>> abjad.f(lilypond_file)
                \score { %! abjad.LilyPondFile
                    <<
                        {
                            \include "layout.ly"
                        }
                        \context Staff = "Custom_Staff"
                        {
                            c'4
                            d'4
                            e'4
                            f'4
                        }
                    >>
                } %! abjad.LilyPondFile

                >>> lilypond_file[abjad.Staff]
                Staff("c'4 d'4 e'4 f'4", name='Custom_Staff')

                >>> lilypond_file['Custom_Staff']
                Staff("c'4 d'4 e'4 f'4", name='Custom_Staff')

        Returns item.

        Raises key error when no item with ``name`` is found.
        """
        if not isinstance(name, str):
            if inspect.isclass(name):
                assert issubclass(name, Component), repr(name)
            else:
                assert isinstance(name, Component), repr(name)
        score = None
        if self.score_block and self.score_block.items:
            items = self.score_block.items
            for container in iterate(items).components(Container):
                if isinstance(container, Context):
                    score = container
                    break
        if isinstance(name, str):
            for item in self.items:
                if getattr(item, "name", None) == name:
                    return item
            if score is not None:
                if score.name == name:
                    return score
                context = score[name]
                return context
            raise KeyError(f"can not find item with name {name!r}.")
        elif isinstance(name, Component):
            for item in self.items:
                if item is name:
                    return item
            if score is not None:
                if score is name:
                    return score
                prototype = Context
                for context in iterate(score).components(prototype):
                    if context is name:
                        return context
            raise KeyError(f"can not find {name}.")
        elif inspect.isclass(name) and issubclass(name, Component):
            for item in self.items:
                if isinstance(item, name):
                    return item
            if score is not None:
                if isinstance(score, name):
                    return score
                prototype = Context
                for context in iterate(score).components(prototype):
                    if isinstance(context, name):
                        return context
            raise KeyError(f"can not find item of class {name}.")
        else:
            raise TypeError(name)
Esempio n. 26
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]
Esempio n. 27
0
    def rhythm(
        class_,
        selections,
        divisions=None,
        attach_lilypond_voice_commands=None,
        implicit_scaling=None,
        pitched_staff=None,
        simultaneous_selections=None,
        time_signatures=None,
    ):
        r"""
        Makes rhythm-styled LilyPond file.

        ..  container:: example

            Makes rhythmic staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 3/4
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 1/4
                        s1 * 1/4
                    }
                    \new RhythmicStaff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Set time signatures explicitly:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     [(6, 8), (4, 8), (2, 8)],
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 6/8
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 2/8
                        s1 * 1/4
                    }
                    \new RhythmicStaff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Makes pitched staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     pitched_staff=True,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        \time 3/4
                        s1 * 3/4
                        \time 4/8
                        s1 * 1/2
                        \time 1/4
                        s1 * 1/4
                    }
                    \new Staff
                    {
                        c'8
                        [
                        c'8
                        c'8
                        c'8
                        c'8
                        c'8
                        ]
                        c'16
                        [
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        c'16
                        ]
                        c'8
                        [
                        c'8
                        ]
                    }
                >>

        ..  container:: example

            Makes simultaneous voices:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> for note in abjad.iterate(selections).components(abjad.Note):
            ...     note.written_pitch = abjad.NamedPitch("e'")
            ...
            >>> selection_1 = selections[0] + selections[1] + selections[2]
            >>> selections = [
            ...     maker(12 * [0], [(1, 16)]),
            ...     maker(16 * [0], [(1, 32)]),
            ...     maker(4 * [0], [(1, 16)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.beam(selection[:])
            ...
            >>> selection_2 = selections[0] + selections[1] + selections[2]
            >>> selections = {
            ...     'Voice_1': selection_1,
            ...     'Voice_2': selection_2,
            ... }
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> voice_1 = lilypond_file['Voice_1']
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceOne'), voice_1)
            >>> voice_2 = lilypond_file['Voice_2']
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceTwo'), voice_2)
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        s1 * 3/4
                        s1 * 1/2
                        s1 * 1/4
                    }
                    \new Staff
                    <<
                        \context Voice = "Voice_1"
                        {
                            \voiceOne
                            e'8
                            [
                            e'8
                            e'8
                            e'8
                            e'8
                            e'8
                            ]
                            e'16
                            [
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            ]
                            e'8
                            [
                            e'8
                            ]
                        }
                        \context Voice = "Voice_2"
                        {
                            \voiceTwo
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                            c'32
                            [
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            ]
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            ]
                        }
                    >>
                >>

        Returns LilyPond file.
        """
        if isinstance(selections, list):
            for selection in selections:
                if not isinstance(selection, Selection):
                    raise TypeError(f"must be selection: {selection!r}.")
        elif isinstance(selections, dict):
            for selection in selections.values():
                if not isinstance(selection, Selection):
                    raise TypeError(f"must be selection: {selection!r}.")
        else:
            raise TypeError(f"must be list or dictionary: {selections!r}.")
        score = Score()
        lilypond_file = LilyPondFile.new(
            score, includes=["default.ily", "rhythm-maker-docs.ily"]
        )
        if pitched_staff is None:
            if isinstance(selections, list):
                selections_ = selections
            elif isinstance(selections, dict):
                selections_ = selections.values()
            else:
                raise TypeError(selections)
            for note in iterate(selections_).leaves(Note):
                if note.written_pitch != NamedPitch("c'"):
                    pitched_staff = True
                    break
        if isinstance(selections, list):
            if divisions is None:
                duration = abjad_inspect(selections).duration()
                divisions = [duration]
            time_signatures = time_signatures or divisions
            time_signatures = [TimeSignature(_) for _ in time_signatures]
            if pitched_staff:
                staff = Staff()
            else:
                staff = Staff(lilypond_type="RhythmicStaff")
            staff.extend(selections)
        elif isinstance(selections, dict):
            voices = []
            for voice_name in sorted(selections):
                selections_ = selections[voice_name]
                selections_ = sequence(selections_).flatten(depth=-1)
                selections_ = copy.deepcopy(selections_)
                voice = Voice(selections_, name=voice_name)
                if attach_lilypond_voice_commands:
                    voice_name_to_command_string = {
                        "Voice_1": "voiceOne",
                        "Voice_2": "voiceTwo",
                        "Voice_3": "voiceThree",
                        "Voice_4": "voiceFour",
                    }
                    command_string = voice_name_to_command_string.get(
                        voice_name
                    )
                    if command_string:
                        command = LilyPondLiteral("\\" + command_string)
                        attach(command, voice)
                voices.append(voice)
            staff = Staff(voices, is_simultaneous=True)
            if divisions is None:
                duration = abjad_inspect(staff).duration()
                divisions = [duration]
        else:
            message = "must be list or dictionary of selections:"
            message += f" {selections!r}."
            raise TypeError(message)
        score.append(staff)
        assert isinstance(divisions, collections.abc.Sequence), repr(divisions)
        time_signatures = time_signatures or divisions
        context = Context(lilypond_type="GlobalContext")
        skips = []
        for time_signature in time_signatures:
            skip = Skip(1)
            skip.multiplier = time_signature
            attach(time_signature, skip, context="Score")
            skips.append(skip)
        context.extend(skips)
        score.insert(0, context)
        return lilypond_file