Пример #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['GlobalSkips']
         contexts.append(context)
     except ValueError:
         pass
     try:
         context = self.score['GlobalRests']
         contexts.append(context)
     except ValueError:
         pass
     for voice in iterate(self.score).components(Voice):
         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).get_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
Пример #2
0
    def __call__(self, expr):
        r'''Calls handler on `expr`.

        Returns none.
        '''
        leaves = iterate(expr).by_class(scoretools.Leaf)
        statement = 'override(leaf).{}.{} = {}'
        statement = statement.format(
            self._grob_name,
            self._attribute_name,
            self._attribute_value,
            )
        if self.maximum_written_duration is not None:
            maximum_statement = 'override(leaf).{}.{} = {}'
            maximum_statement = maximum_statement.format(
                self.maximum_settings['grob_name'],
                self.maximum_settings['attribute_name'],
                self.maximum_settings['attribute_value'],
                )
        for leaf in leaves:
            if self.maximum_written_duration is not None:
                if self.maximum_written_duration <= leaf.written_duration:
                    if maximum_statement is not None:
                        exec(maximum_statement, globals(), locals())
                    continue
            exec(statement, globals(), locals())
Пример #3
0
    def __call__(self, expr, timespan=None):
        r'''Calls handler on `expr`.

        Returns none.
        '''
        leaves = iterate(expr).by_class(scoretools.Leaf)
        statement = 'override(leaf).{}.{} = {}'
        statement = statement.format(
            self._grob_name,
            self._attribute_name,
            self._attribute_value,
            )
        if self.maximum_written_duration is not None:
            maximum_statement = 'override(leaf).{}.{} = {}'
            maximum_statement = maximum_statement.format(
                self.maximum_settings['grob_name'],
                self.maximum_settings['attribute_name'],
                self.maximum_settings['attribute_value'],
                )
        for leaf in leaves:
            if self.maximum_written_duration is not None:
                if self.maximum_written_duration <= leaf.written_duration:
                    if maximum_statement is not None:
                        exec(maximum_statement, globals(), locals())
                    continue
            exec(statement, globals(), locals())
Пример #4
0
    def __call__(self, expr, timespan=None):
        r'''Calls handler on `expr`.

        Returns none.
        '''
        prototype = (scoretools.Note, scoretools.Chord)
        hash_mark_counts = datastructuretools.CyclicTuple(
            self.hash_mark_counts)
        leaves = iterate(expr).by_class(prototype)
        for i, leaf in enumerate(leaves):
            hash_mark_count = hash_mark_counts[i]
            stem_tremolo = indicatortools.StemTremolo(hash_mark_count)
            attach(stem_tremolo, leaf)
Пример #5
0
    def __call__(self, expr):
        r'''Calls handler on `expr`.

        Returns none.
        '''
        prototype = (scoretools.Note, scoretools.Chord)
        hash_mark_counts = datastructuretools.CyclicTuple(
            self.hash_mark_counts)
        leaves = list(iterate(expr).by_class(prototype))
        total_length = len(leaves)
        for i, leaf in enumerate(leaves):
            if self.pattern is not None:
                if not self.pattern.matches_index(i, total_length):
                    continue
            hash_mark_count = hash_mark_counts[i]
            stem_tremolo = indicatortools.StemTremolo(hash_mark_count)
            attach(stem_tremolo, leaf)
Пример #6
0
    def __call__(self, expr):
        r'''Calls handler on `expr`.

        Returns none.
        '''
        prototype = (scoretools.Note, scoretools.Chord)
        hash_mark_counts = datastructuretools.CyclicTuple(
            self.hash_mark_counts)
        leaves = list(iterate(expr).by_class(prototype))
        total_length = len(leaves)
        for i, leaf in enumerate(leaves):
            if self.pattern is not None:
                if not self.pattern.matches_index(i, total_length):
                    continue
            hash_mark_count = hash_mark_counts[i]
            stem_tremolo = indicatortools.StemTremolo(hash_mark_count)
            attach(stem_tremolo, leaf)
Пример #7
0
 def __illustrate__(
     self,
     default_paper_size: str = None,
     global_staff_size: int = None,
     includes: typing.List[str] = None,
 ) -> LilyPondFile:
     r'''Illustrates score template.
     '''
     score = self()
     for voice in iterate(score).components(Voice):
         voice.append(Skip(1))
     self.attach_defaults(score)
     lilypond_file = score.__illustrate__()
     lilypond_file = new(
         lilypond_file,
         default_paper_size=default_paper_size,
         global_staff_size=global_staff_size,
         includes=includes,
     )
     return lilypond_file
Пример #8
0
    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')
Пример #9
0
    def get_leaf(self, n=0):
        r'''Gets leaf `n`.

        ..  container:: example

            Example score:

            ::

                >>> staff = Staff()
                >>> staff.append(Voice("c'8 d'8 e'8 f'8"))
                >>> staff.append(Voice("g'8 a'8 b'8 c''8"))
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> print(format(staff))
                \new Staff {
                    \new Voice {
                        c'8
                        d'8
                        e'8
                        f'8
                    }
                    \new Voice {
                        g'8
                        a'8
                        b'8
                        c''8
                    }
                }

        ..  container:: example

            **Example 1.** Gets leaf `n` **from** client of inspection agent
            when client of inspection agent is a leaf.

            With positive indices:

            ::

                >>> first_leaf = staff[0][0]
                >>> first_leaf
                Note("c'8")

            ::

                >>> for n in range(8):
                ...     print(n, inspect_(first_leaf).get_leaf(n))
                ... 
                0 c'8
                1 d'8
                2 e'8
                3 f'8
                4 None
                5 None
                6 None
                7 None

            With negative indices:

            ::

                >>> last_leaf = staff[0][-1]
                >>> last_leaf
                Note("f'8")

            ::

                >>> for n in range(0, -8, -1):
                ...     print(n, inspect_(last_leaf).get_leaf(n))
                ... 
                0 f'8
                -1 e'8
                -2 d'8
                -3 c'8
                -4 None
                -5 None
                -6 None
                -7 None

        ..  container:: example

            **Example 2.** Gets leaf `n` **in** client of inspection agent
            when client of inspection agent is a container.

            With positive indices:

            ::

                >>> first_voice = staff[0]
                >>> first_voice
                Voice("c'8 d'8 e'8 f'8")

            ::

                >>> for n in range(8):
                ...     print(n, inspect_(first_voice).get_leaf(n))
                ... 
                0 c'8
                1 d'8
                2 e'8
                3 f'8
                4 None
                5 None
                6 None
                7 None

            With negative indices:

            ::

                >>> first_voice = staff[0]
                >>> first_voice
                Voice("c'8 d'8 e'8 f'8")

            ::

                >>> for n in range(-1, -9, -1):
                ...     print(n, inspect_(first_voice).get_leaf(n))
                ... 
                -1 f'8
                -2 e'8
                -3 d'8
                -4 c'8
                -5 None
                -6 None
                -7 None
                -8 None

        Returns leaf or none.
        '''
        from abjad.tools import scoretools
        if isinstance(self._client, scoretools.Leaf):
            return self._client._get_leaf(n=n)
        if 0 <= n:
            leaves = iterate(self._client).by_class(
                scoretools.Leaf,
                start=0,
                stop=n+1,
                )
            leaves = list(leaves)
            if len(leaves) < n + 1:
                return
            leaf = leaves[n]
            return leaf
        else:
            leaves = iterate(self._client).by_class(
                scoretools.Leaf,
                start=0,
                stop=abs(n),
                reverse=True,
                )
            leaves = list(leaves)
            if len(leaves) < abs(n):
                return
            leaf = leaves[abs(n)-1]
            return leaf
    def grade_composition(self, composition: CompositionEnvironment) -> int:
        penalties = 0
        working_staff = StaffGroup()
        working_staff.append(composition.voices[0])
        working_staff.append(composition.voices[1])

        interval_tally = {}
        pitch_tally = {}
        melodic_interval_tally = {}
        vertical_moments = list(iterate(working_staff).by_vertical_moment())
        intervals = []
        degrees = [[], []]

        for moment in vertical_moments:
            pitches = moment.leaves
            harmonic = NamedInterval.from_pitch_carriers(
                pitches[1], pitches[0])
            intervals.append(harmonic)
            degrees[0].append(
                composition.composition_parameters.scale.
                named_pitch_class_to_scale_degree(pitches[0]))
            degrees[1].append(
                composition.composition_parameters.scale.
                named_pitch_class_to_scale_degree(pitches[1]))

            count = pitch_tally.setdefault(pitches[0], 0) + 1
            pitch_tally[pitches[0]] = count

            count = pitch_tally.setdefault(pitches[1], 0) + 1
            pitch_tally[pitches[1]] = count

            count = interval_tally.setdefault(harmonic, 0) + 1
            interval_tally[harmonic] = count

        for i in range(len(vertical_moments)):
            vertical_moment = vertical_moments[i]
            harmonic = intervals[i]

            # No voice crossing
            if harmonic.direction_string == "descending":
                penalties -= 1
            if abs(harmonic.semitones) in constants.dissonant_intervals:
                penalties -= 5
            # No harmonic intervals greater than a 12th
            if abs(harmonic.semitones) > NamedInterval("P12").semitones:
                penalties -= 5
            # Tenth is pushing it
            elif abs(harmonic.semitones) > NamedInterval("M10").semitones:
                penalties -= 1

            maximum_extent = vertical_moment.offset + vertical_moment.leaves[
                0].written_duration
            if maximum_extent == composition.composition_parameters.duration:
                last_top = degrees[0][-1]
                last_bottom = degrees[1][-1]
                prev_top = degrees[0][-2]
                prev_bottom = degrees[1][-2]
                # Use an authentic cadence
                if last_top != ScaleDegree(1):
                    penalties -= 10
                if last_bottom != ScaleDegree(1):
                    penalties -= 10
                if not ((prev_top == ScaleDegree(7)
                         and prev_bottom == ScaleDegree(2)) or
                        (prev_top == ScaleDegree(2)
                         and prev_bottom == ScaleDegree(7))):
                    penalties -= 10

            elif i is 0:
                # First interval should be a tonic unison
                if degrees[0][0] != ScaleDegree(1):
                    penalties -= 5
                if degrees[1][0] != ScaleDegree(1):
                    penalties -= 5
            if i > 0:
                prev_harmonic = intervals[i - 1]
                prev_slice = vertical_moments[i - 1]

                lower_melodic, upper_melodic = slices_to_melodic_intervals(
                    prev_slice, vertical_moment)

                count = melodic_interval_tally.get(lower_melodic, 0) + 1
                melodic_interval_tally[lower_melodic] = count

                count = melodic_interval_tally.get(upper_melodic, 0) + 1
                melodic_interval_tally[upper_melodic] = count

                motion = characterize_relative_motion(upper_melodic,
                                                      lower_melodic)
                # Lines should always be moving
                if motion is RelativeMotion.none:
                    penalties -= 5

                # Contrary motion is preferred
                if motion is RelativeMotion.similar or motion is RelativeMotion.oblique:
                    penalties -= 1

                # Never have two perfect consonances in a row
                if prev_harmonic.interval_class == harmonic.interval_class and harmonic.quality_string == "perfect":
                    penalties -= 5

                # Steps are preferred to leaps
                if is_leap(lower_melodic):
                    penalties -= 1

                if is_leap(upper_melodic):
                    penalties -= 1
                if i > 2:
                    prev_prev_harmonic = intervals[i - 2]
                    prev_prev_prev_harmonic = intervals[i - 3]

                    all_same = same_harmonic_quality(harmonic, prev_harmonic,
                                                     prev_prev_harmonic,
                                                     prev_prev_prev_harmonic)
                    # Don't have the same interval more than three times in a row
                    if all_same:
                        penalties -= 5

                    prev_lower_melodic, prev_upper_harmonic = slices_to_melodic_intervals(
                        vertical_moments[i - 2], prev_slice)

                    # Encourage counterstepwise motion.
                    # If the prev motion was a leap..
                    if is_leap(prev_lower_melodic):
                        # It needs to be resolved by a step, and the step needs to be in the opposite direction
                        if not is_step(lower_melodic) or (
                                prev_lower_melodic.semitones >
                                0 ^ lower_melodic.semitones > 0):
                            penalties -= 5
                        else:
                            ()
                            # print("we did it")

                    if is_leap(prev_upper_harmonic):
                        if not is_step(upper_melodic) or (
                                prev_upper_harmonic.semitones >
                                0 ^ upper_melodic.semitones > 0):
                            penalties -= 5
                        else:
                            ()
                            # print("we did it")
        """
        for pitch, num in pitch_tally.items():
            if num > 2:
                penalties -= 5 * num

        for interval, num in interval_tally.items():
            if num > 5:
                penalties -= 5 * num

        for interval, num in melodic_interval_tally.items():
            if num > 5:
                penalties -= 5 * num
        """

        return penalties
Пример #11
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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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
                    {
                        {   % measure
                            \time 6/8
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 2/8
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 6/8
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 2/8
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new Staff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \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):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        elif isinstance(selections, dict):
            for selection in selections.values():
                if not isinstance(selection, Selection):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        else:
            message = f'must be list or dictionary: {selections!r}.'
            raise TypeError(message)
        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).get_duration()
                divisions = [duration]
            time_signatures = time_signatures or divisions
            maker = MeasureMaker(implicit_scaling=implicit_scaling)
            measures = maker(time_signatures)
            if pitched_staff:
                staff = Staff(measures)
            else:
                staff = Staff(measures, lilypond_type='RhythmicStaff')
            selections = sequence(selections).flatten(depth=-1)
            selections_ = copy.deepcopy(selections)
            try:
                agent = mutate(staff)
                measures = agent.replace_measure_contents(selections)
            except StopIteration:
                if pitched_staff:
                    staff = Staff(selections_)
                else:
                    staff = Staff(
                        selections_,
                        lilypond_type='RhythmicStaff',
                    )
        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).get_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.Sequence), repr(divisions)
        time_signatures = time_signatures or divisions
        context = Context(lilypond_type='GlobalContext')
        maker = MeasureMaker(implicit_scaling=implicit_scaling)
        measures = maker(time_signatures)
        context.extend(measures)
        score.insert(0, context)
        return lilypond_file
Пример #12
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='CustomStaff')
                >>> 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 {
                    <<
                        {
                            \include "layout.ly"
                        }
                        \context Staff = "CustomStaff"
                        {
                            c'4
                            d'4
                            e'4
                            f'4
                        }
                    >>
                }

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

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

        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)
Пример #13
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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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
                    {
                        {   % measure
                            \time 6/8
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 2/8
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 6/8
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 2/8
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new Staff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  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.attach(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.attach(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
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \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):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        elif isinstance(selections, dict):
            for selection in selections.values():
                if not isinstance(selection, Selection):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        else:
            message = f'must be list or dictionary: {selections!r}.'
            raise TypeError(message)
        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).get_duration()
                divisions = [duration]
            time_signatures = time_signatures or divisions
            maker = MeasureMaker(implicit_scaling=implicit_scaling)
            measures = maker(time_signatures)
            if pitched_staff:
                staff = Staff(measures)
            else:
                staff = Staff(measures, lilypond_type='RhythmicStaff')
            selections = sequence(selections).flatten(depth=-1)
            selections_ = copy.deepcopy(selections)
            try:
                agent = mutate(staff)
                measures = agent.replace_measure_contents(selections)
            except StopIteration:
                if pitched_staff:
                    staff = Staff(selections_)
                else:
                    staff = Staff(
                        selections_,
                        lilypond_type='RhythmicStaff',
                        )
        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).get_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.Sequence), repr(divisions)
        time_signatures = time_signatures or divisions
        context = Context(lilypond_type='GlobalContext')
        maker = MeasureMaker(implicit_scaling=implicit_scaling)
        measures = maker(time_signatures)
        context.extend(measures)
        score.insert(0, context)
        return lilypond_file
Пример #14
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='CustomStaff')
                >>> 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 {
                    <<
                        {
                            \include "layout.ly"
                        }
                        \context Staff = "CustomStaff"
                        {
                            c'4
                            d'4
                            e'4
                            f'4
                        }
                    >>
                }

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

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

        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)