<commit_before># -*- encoding: utf-8 -*-
from __future__ import print_function
from abjad import *


class ChordExpression(abctools.AbjadValueObject):
    r'''A chord expression.

    ::

        >>> import consort
        >>> chord_expression = consort.ChordExpression(
        ...     arpeggio_direction=Down,
        ...     interval_numbers=(-1, 3, 7),
        ...     )
        >>> print(format(chord_expression))
        consort.tools.ChordExpression(
            arpeggio_direction=Down,
            interval_numbers=(-1, 3, 7),
            )

    ::

        >>> staff = Staff("c'4 d'4 ~ d'4 e'4")
        >>> pitch_range = pitchtools.PitchRange.from_pitches('C3', 'C6')
        >>> attach(pitch_range, staff, scope=Staff)
        >>> logical_tie = inspect_(staff[1]).get_logical_tie()
        >>> chord_expression(logical_tie)
        >>> f(staff)
        \new Staff {
            c'4
            \arpeggioArrowDown
            <cs' f' a'>4 \arpeggio ~
            <cs' f' a'>4
            e'4
        }

    '''

    ### CLASS VARIABLES ###

    __slots__ = (
        '_arpeggio_direction',
        '_interval_numbers',
        )

    ### INITIALIZER ###

    def __init__(
        self,
        arpeggio_direction=None,
        interval_numbers=None,
        ):
        assert arpeggio_direction in (Up, Down, Center, None)
        if interval_numbers is not None:
            interval_numbers = tuple(sorted(set(interval_numbers)))
            assert len(interval_numbers)
        self._arpeggio_direction = arpeggio_direction
        self._interval_numbers = interval_numbers

    ### SPECIAL METHODS ###

    def __call__(
        self,
        logical_tie,
        pitch_range=None,
        ):
        assert isinstance(logical_tie, selectiontools.LogicalTie), logical_tie
        interval_numbers = self.interval_numbers or ()
        interval_numbers = sorted(list(interval_numbers))
        head = logical_tie.head
        base_pitch = head.written_pitch
        new_interval_numbers = interval_numbers
        if pitch_range is not None:
            assert base_pitch in pitch_range
            maximum = max(interval_numbers)
            minimum = min(interval_numbers)
            maximum_pitch = base_pitch.transpose(maximum)
            minimum_pitch = base_pitch.transpose(minimum)
            if maximum_pitch not in pitch_range:
                new_interval_numbers = [x - maximum for x in interval_numbers]
            elif minimum_pitch not in pitch_range:
                new_interval_numbers = [x - minimum for x in interval_numbers]
        pitches = [base_pitch.transpose(x) for x in new_interval_numbers]
        pitches = [pitchtools.NamedPitch(float(x)) for x in pitches]
        if pitch_range is not None:
            assert all(pitch in pitch_range for pitch in pitches), \
                (pitch_range, base_pitch, interval_numbers, pitches)
        for i, leaf in enumerate(logical_tie):
            chord = scoretools.Chord(leaf)
            chord.written_pitches = pitches
            grace_containers = inspect_(leaf).get_grace_containers('after')
            if grace_containers:
                old_grace_container = grace_containers[0]
                grace_notes = old_grace_container.select_leaves()
                detach(scoretools.GraceContainer, leaf)
            mutate(leaf).replace(chord)
            if not i and self.arpeggio_direction is not None:
                arpeggio = indicatortools.Arpeggio(self.arpeggio_direction)
                attach(arpeggio, chord)
            if grace_containers:
                new_grace_container = scoretools.GraceContainer(
                    grace_notes,
                    kind='after',
                    )
                attach(new_grace_container, chord)

    ### PUBLIC PROPERTIES ###

    @property
    def arpeggio_direction(self):
        return self._arpeggio_direction

    @property
    def interval_numbers(self):
        return self._interval_numbers<commit_msg>ChordExpression now inherits from LogicalTieExpression.<commit_after># -*- encoding: utf-8 -*-
from __future__ import print_function
from abjad import attach
from abjad import indicatortools
from abjad import pitchtools
from abjad import scoretools
from abjad import selectiontools
from consort.tools.LogicalTieExpression import LogicalTieExpression


class ChordExpression(LogicalTieExpression):
    r'''A chord expression.

    ::

        >>> import consort
        >>> chord_expression = consort.ChordExpression(
        ...     arpeggio_direction=Down,
        ...     interval_numbers=(-1, 3, 7),
        ...     )
        >>> print(format(chord_expression))
        consort.tools.ChordExpression(
            arpeggio_direction=Down,
            interval_numbers=(-1, 3, 7),
            )

    ::

        >>> staff = Staff("c'4 d'4 ~ d'4 e'4")
        >>> pitch_range = pitchtools.PitchRange.from_pitches('C3', 'C6')
        >>> attach(pitch_range, staff, scope=Staff)
        >>> logical_tie = inspect_(staff[1]).get_logical_tie()
        >>> chord_expression(logical_tie)
        >>> print(format(staff))
        \new Staff {
            c'4
            \arpeggioArrowDown
            <cs' f' a'>4 \arpeggio ~
            <cs' f' a'>4
            e'4
        }

    '''

    ### CLASS VARIABLES ###

    __slots__ = (
        '_arpeggio_direction',
        '_interval_numbers',
        )

    ### INITIALIZER ###

    def __init__(
        self,
        arpeggio_direction=None,
        interval_numbers=None,
        ):
        assert arpeggio_direction in (Up, Down, Center, None)
        if interval_numbers is not None:
            interval_numbers = tuple(sorted(set(interval_numbers)))
            assert len(interval_numbers)
        self._arpeggio_direction = arpeggio_direction
        self._interval_numbers = interval_numbers

    ### SPECIAL METHODS ###

    def __call__(
        self,
        logical_tie,
        pitch_range=None,
        ):
        assert isinstance(logical_tie, selectiontools.LogicalTie), logical_tie
        interval_numbers = self.interval_numbers or ()
        interval_numbers = sorted(list(interval_numbers))
        head = logical_tie.head
        base_pitch = head.written_pitch
        new_interval_numbers = interval_numbers
        if pitch_range is not None:
            assert base_pitch in pitch_range
            maximum = max(interval_numbers)
            minimum = min(interval_numbers)
            maximum_pitch = base_pitch.transpose(maximum)
            minimum_pitch = base_pitch.transpose(minimum)
            if maximum_pitch not in pitch_range:
                new_interval_numbers = [x - maximum for x in interval_numbers]
            elif minimum_pitch not in pitch_range:
                new_interval_numbers = [x - minimum for x in interval_numbers]
        pitches = [base_pitch.transpose(x) for x in new_interval_numbers]
        pitches = [pitchtools.NamedPitch(float(x)) for x in pitches]
        if pitch_range is not None:
            assert all(pitch in pitch_range for pitch in pitches), \
                (pitch_range, base_pitch, interval_numbers, pitches)
        for i, leaf in enumerate(logical_tie):
            chord = scoretools.Chord(leaf)
            chord.written_pitches = pitches
            self._replace(leaf, chord)
            if not i and self.arpeggio_direction is not None:
                arpeggio = indicatortools.Arpeggio(self.arpeggio_direction)
                attach(arpeggio, chord)

    ### PUBLIC PROPERTIES ###

    @property
    def arpeggio_direction(self):
        return self._arpeggio_direction

    @property
    def interval_numbers(self):
        return self._interval_numbers
{'fraction_non_alphanumeric': 0.0877444589308996, 'fraction_numerical': 0.004823989569752282, 'mean_word_length': 2.155491567256273, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5427501', 'n_tokens_mistral': 2341, 'n_tokens_neox': 2161, 'n_words': 469}