예제 #1
0
파일: Measure.py 프로젝트: DnMllr/abjad
 def _duration_and_possible_denominators_to_time_signature(
     duration,
     denominators=None,
     factor=None,
     ):
     # check input
     duration = durationtools.Duration(duration)
     if denominators is not None:
         if factor is not None:
             denominators = [
                 d for d in denominators
                 if factor in mathtools.factors(d)
                 ]
         for desired_denominator in sorted(denominators):
             nonreduced_fraction = mathtools.NonreducedFraction(duration)
             candidate_pair = \
                 nonreduced_fraction.with_denominator(desired_denominator)
             if candidate_pair.denominator == desired_denominator:
                 return indicatortools.TimeSignature(candidate_pair)
     if factor is not None:
         if factor in mathtools.factors(duration.denominator):
             return indicatortools.TimeSignature(duration)
         else:
             time_signature_numerator = factor * duration.numerator
             time_signature_denominator = factor * duration.denominator
             return indicatortools.TimeSignature(
                 (time_signature_numerator, time_signature_denominator))
     else:
         return indicatortools.TimeSignature(duration)
예제 #2
0
 def _duration_and_possible_denominators_to_time_signature(
     duration,
     denominators=None,
     factor=None,
 ):
     # check input
     duration = durationtools.Duration(duration)
     if denominators is not None:
         if factor is not None:
             denominators = [
                 d for d in denominators if factor in mathtools.factors(d)
             ]
         for desired_denominator in sorted(denominators):
             nonreduced_fraction = mathtools.NonreducedFraction(duration)
             candidate_pair = \
                 nonreduced_fraction.with_denominator(desired_denominator)
             if candidate_pair.denominator == desired_denominator:
                 return indicatortools.TimeSignature(candidate_pair)
     if factor is not None:
         if factor in mathtools.factors(duration.denominator):
             return indicatortools.TimeSignature(duration)
         else:
             time_signature_numerator = factor * duration.numerator
             time_signature_denominator = factor * duration.denominator
             return indicatortools.TimeSignature(
                 (time_signature_numerator, time_signature_denominator))
     else:
         return indicatortools.TimeSignature(duration)
예제 #3
0
def _least_common_multiple_helper(m, n):
    from abjad.tools import mathtools

    # check input
    if not isinstance(m, int):
        raise TypeError

    if not isinstance(n, int):
        raise TypeError

    # find factors of m and n
    factors_m = mathtools.factors(m)
    factors_n = mathtools.factors(n)

    # remove duplicated shared factors
    for x in factors_m:
        try:
            factors_n.remove(x)
        except ValueError:
            pass

    # calculate product of shared factors
    result = 1
    for x in factors_m + factors_n:
        result *= x

    # return product
    return result
예제 #4
0
def _least_common_multiple_helper(m, n):
    from abjad.tools import mathtools

    # check input
    if not isinstance(m, int):
        raise TypeError

    if not isinstance(n, int):
        raise TypeError

    # find factors of m and n
    factors_m = mathtools.factors(m)
    factors_n = mathtools.factors(n)

    # remove duplicated shared factors
    for x in factors_m:
        try:
            factors_n.remove(x)
        except ValueError:
            pass

    # calculate product of shared factors
    result = 1
    for x in factors_m + factors_n:
        result *= x

    # return product
    return result
예제 #5
0
def _least_common_multiple_helper(m, n):
    from abjad.tools import mathtools
    assert isinstance(m, int), repr(m)
    assert isinstance(n, int), repr(n)
    factors_m = mathtools.factors(m)
    factors_n = mathtools.factors(n)
    for x in factors_m:
        try:
            factors_n.remove(x)
        except ValueError:
            pass
    result = 1
    for x in factors_m + factors_n:
        result *= x
    return result
예제 #6
0
 def _group_nonreduced_fractions_by_implied_prolation(durations):
     durations = [
         mathtools.NonreducedFraction(duration) for duration in durations
     ]
     assert 0 < len(durations)
     group = [durations[0]]
     result = [group]
     for d in durations[1:]:
         d_f = set(mathtools.factors(d.denominator))
         d_f.discard(2)
         gd_f = set(mathtools.factors(group[0].denominator))
         gd_f.discard(2)
         if d_f == gd_f:
             group.append(d)
         else:
             group = [d]
             result.append(group)
     return result
예제 #7
0
 def _group_nonreduced_fractions_by_implied_prolation(durations):
     durations = [
         mathtools.NonreducedFraction(duration)
         for duration in durations
         ]
     assert 0 < len(durations)
     group = [durations[0]]
     result = [group]
     for d in durations[1:]:
         d_f = set(mathtools.factors(d.denominator))
         d_f.discard(2)
         gd_f = set(mathtools.factors(group[0].denominator))
         gd_f.discard(2)
         if d_f == gd_f:
             group.append(d)
         else:
             group = [d]
             result.append(group)
     return result
예제 #8
0
def is_dotted_integer(expr):
    """True when `expr` is equivalent to a positive integer and
    can be written with zero or more dots.

    ::

        >>> for expr in range(16):
        ...     print '%s\t%s' % (expr, mathtools.is_dotted_integer(expr))
        ...
        0         False
        1         False
        2         False
        3         True
        4         False
        5         False
        6         True
        7         True
        8         False
        9         False
        10        False
        11        False
        12        True
        13        False
        14        True
        15        True

    Otherwise false.

    Returns boolean.

    Integer `n` qualifies as dotted when ``abs(n)`` is of the form
    ``2**j * (2**k - 1)`` with integers ``0 <= j``, ``2 < k``.
    """
    from abjad.tools import mathtools

    if expr == 0:
        return False

    non_two_product = 1
    non_two_factors = [d for d in mathtools.factors(expr) if not d == 2]
    for non_two_factor in non_two_factors:
        non_two_product *= non_two_factor

    x = math.log(abs(non_two_product) + 1, 2)

    result = 1 < abs(non_two_product) and int(x) == x

    return result
예제 #9
0
def is_dotted_integer(expr):
    '''Is true when `expr` is equivalent to a positive integer and
    can be written with zero or more dots.

    ::

        >>> for expr in range(16):
        ...     print('%s\t%s' % (expr, mathtools.is_dotted_integer(expr)))
        ... 
        0         False
        1         False
        2         False
        3         True
        4         False
        5         False
        6         True
        7         True
        8         False
        9         False
        10        False
        11        False
        12        True
        13        False
        14        True
        15        True

    Otherwise false.

    Returns true or false.

    Integer `n` qualifies as dotted when ``abs(n)`` is of the form
    ``2**j * (2**k - 1)`` with integers ``0 <= j``, ``2 < k``.
    '''
    from abjad.tools import mathtools

    if expr == 0:
        return False

    non_two_product = 1
    non_two_factors = [d for d in mathtools.factors(expr) if not d == 2]
    for non_two_factor in non_two_factors:
        non_two_product *= non_two_factor

    x = math.log(abs(non_two_product) + 1, 2)

    result = 1 < abs(non_two_product) and int(x) == x

    return result
예제 #10
0
def are_relatively_prime(expr):
    '''Is true when `expr` is a sequence comprising zero or more numbers,
    all of which are relatively prime.

    ::

        >>> mathtools.are_relatively_prime([13, 14, 15])
        True

    Otherwise false:

    ::

        >>> mathtools.are_relatively_prime([13, 14, 15, 16])
        False

    Returns true when `expr` is an empty sequence:

    ::

        >>> mathtools.are_relatively_prime([])
        True

    Returns false when `expr` is nonsensical type:

    ::

        >>> mathtools.are_relatively_prime('foo')
        False

    Returns boolean.
    '''
    from abjad.tools import mathtools

    try:
        all_factors = set([])
        for number in expr:
            current_factors = mathtools.factors(number)
            current_factors.remove(1)
            current_factors = set(current_factors)
            if all_factors & current_factors:
                return False
            all_factors.update(current_factors)
        return True
    # TODO: remove unqualified except
    except:
        return False
예제 #11
0
def are_relatively_prime(numbers_):
    '''Is true when `numbers_` is a sequence comprising zero or more numbers,
    all of which are relatively prime.

    ::

        >>> mathtools.are_relatively_prime([13, 14, 15])
        True

    Otherwise false:

    ::

        >>> mathtools.are_relatively_prime([13, 14, 15, 16])
        False

    Returns true when `numbers_` is an empty sequence:

    ::

        >>> mathtools.are_relatively_prime([])
        True

    Returns false when `numbers_` is nonsensical type:

    ::

        >>> mathtools.are_relatively_prime('foo')
        False

    Returns boolean.
    '''
    from abjad.tools import mathtools

    if not all(isinstance(_, numbers.Number) for _ in numbers_):
        return False

    all_factors = set([])
    for number in numbers_:
        current_factors = mathtools.factors(number)
        current_factors = set(current_factors)
        if all_factors & current_factors:
            return False
        all_factors.update(current_factors)
    return True
예제 #12
0
def are_relatively_prime(argument):
    '''Is true when `argument` is an iterable collection of relative primes.
    Otherwise false.

    ..  container:: example

        >>> abjad.mathtools.are_relatively_prime([13, 14, 15])
        True

        >>> abjad.mathtools.are_relatively_prime([13, 14, 15, 16])
        False

        >>> abjad.mathtools.are_relatively_prime('text')
        False

    ..  container:: example

        Returns true when `argument` is empty:

        >>> abjad.mathtools.are_relatively_prime([])
        True

    Returns true or false.
    '''
    from abjad.tools import mathtools
    if not isinstance(argument, collections.Iterable):
        return False
    if not all(isinstance(_, numbers.Number) for _ in argument):
        return False
    all_factors = set([])
    for number in argument:
        current_factors = mathtools.factors(number)
        current_factors = set(current_factors)
        if all_factors & current_factors:
            return False
        all_factors.update(current_factors)
    return True
예제 #13
0
    def __init__(
        self,
        arg=None,
        decrease_durations_monotonically=True,
        preferred_boundary_depth=None,
    ):

        arg = arg or (4, 4)
        assert isinstance(preferred_boundary_depth, (int, type(None)))
        self._preferred_boundary_depth = preferred_boundary_depth

        def recurse(
            node,
            factors,
            denominator,
            decrease_durations_monotonically,
        ):
            if factors:
                factor, factors = factors[0], factors[1:]
                preprolated_duration = \
                    node.preprolated_duration.__div__(factor)
                #if factor in (2, 3, 4, 5):
                if factor in (2, 3, 4):
                    if factors:
                        for _ in range(factor):
                            child = rhythmtreetools.RhythmTreeContainer(
                                preprolated_duration=preprolated_duration)
                            node.append(child)
                            recurse(
                                child,
                                factors,
                                denominator,
                                decrease_durations_monotonically,
                            )
                    else:
                        for _ in range(factor):
                            node.append(
                                rhythmtreetools.RhythmTreeLeaf(
                                    preprolated_duration=(1, denominator)))
                else:
                    parts = [3]
                    total = 3
                    while total < factor:
                        if decrease_durations_monotonically:
                            parts.append(2)
                        else:
                            parts.insert(0, 2)
                        total += 2
                    for part in parts:
                        grouping = rhythmtreetools.RhythmTreeContainer(
                            preprolated_duration=part * preprolated_duration)
                        if factors:
                            for _ in range(part):
                                child = rhythmtreetools.RhythmTreeContainer(
                                    preprolated_duration=preprolated_duration)
                                grouping.append(child)
                                recurse(
                                    child,
                                    factors,
                                    denominator,
                                    decrease_durations_monotonically,
                                )
                        else:
                            for _ in range(part):
                                grouping.append(
                                    rhythmtreetools.RhythmTreeLeaf(
                                        preprolated_duration=(1, denominator)))
                        node.append(grouping)
            else:
                node.extend([
                    rhythmtreetools.RhythmTreeLeaf(
                        preprolated_duration=(1, denominator))
                    for _ in range(node.preprolated_duration.numerator)
                ])

        decrease_durations_monotonically = \
            bool(decrease_durations_monotonically)

        if isinstance(arg, type(self)):
            root = arg.root_node
            numerator, denominator = arg.numerator, arg.denominator
            decrease_durations_monotonically = \
                arg.decrease_durations_monotonically

        elif isinstance(arg, (str, rhythmtreetools.RhythmTreeContainer)):
            if isinstance(arg, str):
                parsed = rhythmtreetools.RhythmTreeParser()(arg)
                assert len(parsed) == 1
                root = parsed[0]
            else:
                root = arg
            for node in root.nodes:
                assert node.prolation == 1
            numerator = root.preprolated_duration.numerator
            denominator = root.preprolated_duration.denominator

        elif (isinstance(arg, (tuple, scoretools.Measure))
              or (hasattr(arg, 'numerator') and hasattr(arg, 'denominator'))):
            if isinstance(arg, tuple):
                fraction = mathtools.NonreducedFraction(arg)
            elif isinstance(arg, scoretools.Measure):
                time_signature = arg._get_effective(
                    indicatortools.TimeSignature)
                fraction = mathtools.NonreducedFraction(
                    time_signature.numerator, time_signature.denominator)
            else:
                fraction = mathtools.NonreducedFraction(
                    arg.numerator, arg.denominator)
            numerator, denominator = fraction.numerator, fraction.denominator
            factors = mathtools.factors(numerator)
            # group two nested levels of 2s into a 4
            if 1 < len(factors) and factors[0] == factors[1] == 2:
                factors[0:2] = [4]
            root = rhythmtreetools.RhythmTreeContainer(
                preprolated_duration=fraction)
            recurse(
                root,
                factors,
                denominator,
                decrease_durations_monotonically,
            )

        else:
            message = 'can not initialize {}: {!r}.'
            message = message.format(type(self).__name__, arg)
            raise ValueError(message)

        self._root_node = root
        self._numerator = numerator
        self._denominator = denominator
        self._decrease_durations_monotonically = \
            decrease_durations_monotonically
예제 #14
0
    def multiply_with_cross_cancelation(self, multiplier):
        '''Multiplies nonreduced fraction by `expr` with cross-cancelation.

        ::

            >>> fraction = mathtools.NonreducedFraction(4, 8)

        ::

            >>> fraction.multiply_with_cross_cancelation((2, 3))
            NonreducedFraction(4, 12)

        ::

            >>> fraction.multiply_with_cross_cancelation((4, 1))
            NonreducedFraction(4, 2)

        ::

            >>> fraction.multiply_with_cross_cancelation((3, 5))
            NonreducedFraction(12, 40)

        ::

            >>> fraction.multiply_with_cross_cancelation((6, 5))
            NonreducedFraction(12, 20)

        ::

            >>> fraction = mathtools.NonreducedFraction(5, 6)
            >>> fraction.multiply_with_cross_cancelation((6, 5))
            NonreducedFraction(1, 1)

        Returns nonreduced fraction.
        '''
        from abjad.tools import durationtools
        from abjad.tools import mathtools

        multiplier = durationtools.Multiplier(multiplier)

        self_numerator_factors = mathtools.factors(self.numerator)
        multiplier_denominator_factors = mathtools.factors(
            multiplier.denominator)
        for factor in multiplier_denominator_factors[:]:
            if factor in self_numerator_factors:
                self_numerator_factors.remove(factor)
                multiplier_denominator_factors.remove(factor)

        self_denominator_factors = mathtools.factors(self.denominator)
        multiplier_numerator_factors = mathtools.factors(multiplier.numerator)
        for factor in multiplier_numerator_factors[:]:
            if factor in self_denominator_factors:
                self_denominator_factors.remove(factor)
                multiplier_numerator_factors.remove(factor)

        result_numerator_factors = self_numerator_factors + \
            multiplier_numerator_factors
        result_denominator_factors = self_denominator_factors + \
            multiplier_denominator_factors

        result_numerator = 1
        for factor in result_numerator_factors:
            result_numerator *= factor

        result_denominator = 1
        for factor in result_denominator_factors:
            result_denominator *= factor

        return NonreducedFraction(result_numerator, result_denominator)
예제 #15
0
def test_mathtools_factors_04():
    t = mathtools.factors(4)
    assert t == [1, 2, 2]
예제 #16
0
def make_notes(pitches, durations, decrease_durations_monotonically=True):
    r'''Make notes according to `pitches` and `durations`.

    Cycle through `pitches` when the length of `pitches` is less than the
    length of `durations`:

    ::

        >>> notetools.make_notes([0], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("c'8"), Note("c'8"))

    Cycle through `durations` when the length of `durations` is less than the
    length of `pitches`:

    ::

        >>> notetools.make_notes([0, 2, 4, 5, 7], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8"))

    Create ad hoc tuplets for nonassignable durations:

    ::

        >>> notetools.make_notes([0], [(1, 16), (1, 12), (1, 8)])
        Selection(Note("c'16"), Tuplet(2/3, [c'8]), Note("c'8"))

    Set ``decrease_durations_monotonically=True`` to express tied values 
    in decreasing duration:

    ::

        >>> notetools.make_notes(
        ...     [0], 
        ...     [(13, 16)], 
        ...     decrease_durations_monotonically=True,
        ...     )
        Selection(Note("c'2."), Note("c'16"))

    Set ``decrease_durations_monotonically=False`` to express tied 
    values in increasing duration:

    ::

        >>> notetools.make_notes(
        ...     [0], 
        ...     [(13, 16)], 
        ...     decrease_durations_monotonically=False,
        ...     )
        Selection(Note("c'16"), Note("c'2."))

    Set `pitches` to a single pitch or a sequence of pitches.

    Set `durations` to a single duration or a list of durations.

    Returns list of newly constructed notes.
    '''
    from abjad.tools import leaftools
    from abjad.tools import notetools
    from abjad.tools import selectiontools
    from abjad.tools import tuplettools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    duration_pairs = [durationtools.Duration(duration) 
        for duration in durations]

    # set lists of pitches and duration pairs to the same length
    size = max(len(duration_pairs), len(pitches))
    duration_pairs = \
        sequencetools.repeat_sequence_to_length(duration_pairs, size)
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)

    Duration = durationtools.Duration
    durations = Duration._group_nonreduced_fractions_by_implied_prolation(
        duration_pairs)

    def _make_unprolated_notes(
        pitches,
        durations,
        decrease_durations_monotonically=decrease_durations_monotonically,
        ):
        assert len(pitches) == len(durations)
        result = []
        for pitch, duration in zip(pitches, durations):
            result.extend(leaftools.make_tied_leaf(
                notetools.Note,
                duration,
                pitches=pitch,
                decrease_durations_monotonically=decrease_durations_monotonically,
                ))
        return result

    result = []
    for duration in durations:
        # get factors in denominator of duration group duration other than 1, 2.
        factors = set(mathtools.factors(duration[0].denominator))
        factors.discard(1)
        factors.discard(2)
        ps = pitches[0:len(duration)]
        pitches = pitches[len(duration):]
        if len(factors) == 0:
            result.extend(_make_unprolated_notes(ps, duration,
                decrease_durations_monotonically=decrease_durations_monotonically))
        else:
            # compute prolation
            denominator = duration[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / fractions.Fraction(*multiplier)
            duration = [ratio * durationtools.Duration(d) for d in duration]
            ns = _make_unprolated_notes(ps, duration,
                decrease_durations_monotonically=decrease_durations_monotonically)
            t = tuplettools.Tuplet(multiplier, ns)
            result.append(t)

    # return result
    result = selectiontools.Selection(result)
    return result
예제 #17
0
 def _split_by_duration(
     self,
     duration,
     fracture_spanners=False,
     tie_split_notes=True,
     use_messiaen_style_ties=False,
     ):
     from abjad.tools import scoretools
     from abjad.tools import selectiontools
     # check input
     duration = durationtools.Duration(duration)
     assert 0 <= duration, repr(duration)
     # if zero duration then return empty list and self
     if duration == 0:
         return [], self
     # get split point score offset
     global_split_point = self._get_timespan().start_offset + duration
     # get any duration-crossing descendents
     cross_offset = self._get_timespan().start_offset + duration
     duration_crossing_descendants = []
     for descendant in self._get_descendants():
         start_offset = descendant._get_timespan().start_offset
         stop_offset = descendant._get_timespan().stop_offset
         if start_offset < cross_offset < stop_offset:
             duration_crossing_descendants.append(descendant)
     # get any duration-crossing measure descendents
     measures = [
         x for x in duration_crossing_descendants
         if isinstance(x, scoretools.Measure)
         ]
     # if we must split a power-of-two measure at non-power-of-two
     # split point then go ahead and transform the power-of-two measure
     # to non-power-of-two equivalent now;
     # code that crawls and splits later on will be happier
     if len(measures) == 1:
         measure = measures[0]
         split_point_in_measure = \
             global_split_point - measure._get_timespan().start_offset
         if measure.has_non_power_of_two_denominator:
             if not measure.implied_prolation == \
                 split_point_in_measure.implied_prolation:
                 raise NotImplementedError
         elif not mathtools.is_nonnegative_integer_power_of_two(
             split_point_in_measure.denominator):
             non_power_of_two_factors = mathtools.remove_powers_of_two(
                 split_point_in_measure.denominator)
             non_power_of_two_factors = mathtools.factors(
                 non_power_of_two_factors)
             non_power_of_two_product = 1
             for non_power_of_two_factor in non_power_of_two_factors:
                 non_power_of_two_product *= non_power_of_two_factor
             scoretools.scale_measure_denominator_and_adjust_measure_contents(
                 measure, non_power_of_two_product)
             # rederive duration crosses with possibly new measure contents
             cross_offset = self._get_timespan().start_offset + duration
             duration_crossing_descendants = []
             for descendant in self._get_descendants():
                 start_offset = descendant._get_timespan().start_offset
                 stop_offset = descendant._get_timespan().stop_offset
                 if start_offset < cross_offset < stop_offset:
                     duration_crossing_descendants.append(descendant)
     elif 1 < len(measures):
         message = 'measures can not nest.'
         raise Exception(message)
     # 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, scoretools.Leaf):
         assert isinstance(bottom, scoretools.Leaf)
         did_split_leaf = True
         split_point_in_bottom = \
             global_split_point - bottom._get_timespan().start_offset
         left_list, right_list = bottom._split_by_duration(
             split_point_in_bottom,
             fracture_spanners=fracture_spanners,
             tie_split_notes=tie_split_notes,
             use_messiaen_style_ties=use_messiaen_style_ties,
             )
         right = right_list[0]
         leaf_right_of_split = right
         leaf_left_of_split = left_list[-1]
         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).by_class(scoretools.Leaf):
             if leaf._get_timespan().start_offset == global_split_point:
                 leaf_right_of_split = leaf
                 leaf_left_of_split = leaf_right_of_split._get_leaf(-1)
                 break
         else:
             message = 'can not split empty container {!r}.'
             message = message.format(bottom)
             raise Exception(message)
     # find component to right of split that is also immediate child of
     # last duration-crossing container
     for component in \
         leaf_right_of_split._get_parentage(include_self=True):
         if component._parent is duration_crossing_containers[-1]:
             highest_level_component_right_of_split = component
             break
     else:
         message = 'should we be able to get here?'
         raise ValueError(message)
     # crawl back up through duration-crossing containers and
     # fracture spanners if requested
     if fracture_spanners:
         start_offset = leaf_right_of_split._get_timespan().start_offset
         for parent in leaf_right_of_split._get_parentage():
             if parent._get_timespan().start_offset == start_offset:
                 for spanner in parent._get_spanners():
                     index = spanner._index(parent)
                     spanner._fracture(index, direction=Left)
             if parent is component:
                 break
     # crawl back up through duration-crossing containers and split each
     previous = highest_level_component_right_of_split
     for duration_crossing_container in \
         reversed(duration_crossing_containers):
         assert isinstance(
             duration_crossing_container, scoretools.Container)
         i = duration_crossing_container.index(previous)
         left, right = duration_crossing_container._split_at_index(
             i,
             fracture_spanners=fracture_spanners,
             )
         previous = right
     # NOTE: If logical tie here is convenience, then fusing is good.
     #       If logical tie here is user-given, then fusing is less good.
     #       Maybe later model difference between user logical ties and not.
     left_logical_tie = leaf_left_of_split._get_logical_tie()
     right_logical_tie = leaf_right_of_split._get_logical_tie()
     left_logical_tie._fuse_leaves_by_immediate_parent()
     right_logical_tie._fuse_leaves_by_immediate_parent()
     # 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, scoretools.Note)):
             if (leaf_left_of_split._get_parentage().root is
                 leaf_right_of_split._get_parentage().root):
                 leaves_around_split = \
                     (leaf_left_of_split, leaf_right_of_split)
                 selection = selectiontools.ContiguousSelection(
                     leaves_around_split)
                 selection._attach_tie_spanner_to_leaf_pair(
                     use_messiaen_style_ties=use_messiaen_style_ties,
                     )
     # return pair of left and right list-wrapped halves of container
     return ([left], [right])
예제 #18
0
def test_mathtools_factors_06():
    t = mathtools.factors(12)
    assert t == [1, 2, 2, 3]
예제 #19
0
def make_notes(pitches, durations, decrease_durations_monotonically=True):
    r'''Make notes according to `pitches` and `durations`.

    Cycle through `pitches` when the length of `pitches` is less than the
    length of `durations`:

    ::

        >>> scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("c'8"), Note("c'8"))

    Cycle through `durations` when the length of `durations` is less than the
    length of `pitches`:

    ::

        >>> scoretools.make_notes([0, 2, 4, 5, 7], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8"))

    Create ad hoc tuplets for nonassignable durations:

    ::

        >>> scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)])
        Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8"))

    Set ``decrease_durations_monotonically=True`` to express tied values
    in decreasing duration:

    ::

        >>> scoretools.make_notes(
        ...     [0],
        ...     [(13, 16)],
        ...     decrease_durations_monotonically=True,
        ...     )
        Selection(Note("c'2."), Note("c'16"))

    Set ``decrease_durations_monotonically=False`` to express tied
    values in increasing duration:

    ::

        >>> scoretools.make_notes(
        ...     [0],
        ...     [(13, 16)],
        ...     decrease_durations_monotonically=False,
        ...     )
        Selection(Note("c'16"), Note("c'2."))

    Set `pitches` to a single pitch or a sequence of pitches.

    Set `durations` to a single duration or a list of durations.

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

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions,
        size,
    )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    durations = Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    def _make_unprolated_notes(
        pitches,
        durations,
        decrease_durations_monotonically=decrease_durations_monotonically,
    ):
        assert len(pitches) == len(durations)
        result = []
        for pitch, duration in zip(pitches, durations):
            result.extend(
                scoretools.make_tied_leaf(
                    scoretools.Note,
                    duration,
                    pitches=pitch,
                    decrease_durations_monotonically=
                    decrease_durations_monotonically,
                ))
        return result

    result = []
    for duration in durations:
        # get factors in denominator of duration group duration other than 1, 2.
        factors = set(mathtools.factors(duration[0].denominator))
        factors.discard(1)
        factors.discard(2)
        ps = pitches[0:len(duration)]
        pitches = pitches[len(duration):]
        if len(factors) == 0:
            result.extend(
                _make_unprolated_notes(ps,
                                       duration,
                                       decrease_durations_monotonically=
                                       decrease_durations_monotonically))
        else:
            # compute prolation
            denominator = duration[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / fractions.Fraction(*multiplier)
            duration = [ratio * durationtools.Duration(d) for d in duration]
            ns = _make_unprolated_notes(ps,
                                        duration,
                                        decrease_durations_monotonically=
                                        decrease_durations_monotonically)
            t = scoretools.Tuplet(multiplier, ns)
            result.append(t)

    # return result
    result = selectiontools.Selection(result)
    return result
def duration_and_possible_denominators_to_time_signature(
    duration,
    denominators=None,
    factor=None,
    ):
    r'''Make new time signature equal to `duration`:

    ::

        >>> timesignaturetools.duration_and_possible_denominators_to_time_signature(
        ...     Duration(3, 2))
        TimeSignatureMark((3, 2))

    Make new time signature equal to `duration` with denominator equal to the
    first possible element in `denominators`:

    ::

        >>> timesignaturetools.duration_and_possible_denominators_to_time_signature(
        ...     Duration(3, 2), denominators=[5, 6, 7, 8])
        TimeSignatureMark((9, 6))

    Make new time signature equal to `duration` with denominator divisible by
    `factor`:

    ::

        >>> timesignaturetools.duration_and_possible_denominators_to_time_signature(
        ...     Duration(3, 2), factor=5)
        TimeSignatureMark((15, 10))

    .. note:: possibly divide this into two separate functions?

    Returns new time signature.
    '''

    # check input
    duration = durationtools.Duration(duration)

    if denominators is not None:
        if factor is not None:
            denominators = [
                d for d in denominators 
                if factor in mathtools.factors(d)
                ]
        for desired_denominator in sorted(denominators):
            nonreduced_fraction = mathtools.NonreducedFraction(duration)
            candidate_pair = \
                nonreduced_fraction.with_denominator(desired_denominator)
            if candidate_pair.denominator == desired_denominator:
                return contexttools.TimeSignatureMark(candidate_pair)
    if factor is not None:
        if factor in mathtools.factors(duration.denominator):
            return contexttools.TimeSignatureMark(duration)
        else:
            time_signature_numerator = factor * duration.numerator
            time_signature_denominator = factor * duration.denominator
            return contexttools.TimeSignatureMark(
                (time_signature_numerator, time_signature_denominator))
    else:
        return contexttools.TimeSignatureMark(duration)
예제 #21
0
def make_leaves(
    pitches,
    durations,
    decrease_durations_monotonically=True,
    tie_rests=False,
    forbidden_written_duration=None,
    metrical_hiearchy=None,
    ):
    r'''Make leaves.

    ..  container:: example
    
        **Example 1.** Integer and string elements in `pitches` result in 
        notes:

        ::

            >>> pitches = [2, 4, 'F#5', 'G#5']
            >>> duration = Duration(1, 4)
            >>> leaves = leaftools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                d'4
                e'4
                fs''4
                gs''4
            }

    ..  container:: example
    
        **Example 2.** Tuple elements in `pitches` result in chords:

        ::

            >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')]
            >>> duration = Duration(1, 2)
            >>> leaves = leaftools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                <c' d' e'>2
                <fs'' gs'' as''>2
            }

    ..  container:: example
        
        **Example 3.** None-valued elements in `pitches` result in rests:

        ::

            >>> pitches = 4 * [None]
            >>> durations = [Duration(1, 4)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = stafftools.RhythmicStaff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff {
                r4
                r4
                r4
                r4
            }

    ..  container:: example
        
        **Example 4.** You can mix and match values passed to `pitches`:

        ::

            >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5']
            >>> durations = [Duration(1, 4)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                <c' d' e'>4
                r4
                cs''4
                ds''4
            }

    ..  container:: example
            
        **Example 5.** Read `pitches` cyclically when the length of `pitches`
        is less than the length of `durations`:

        ::

            >>> pitches = ['C5']
            >>> durations = 2 * [Duration(3, 8), Duration(1, 8)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                c''4.
                c''8
                c''4.
                c''8
            }

    ..  container:: example
            
        **Example 6.** Read `durations` cyclically when the length of 
        `durations` is less than the length of `pitches`:

        ::

            >>> pitches = "c'' d'' e'' f''"
            >>> durations = [Duration(1, 4)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

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

    ..  container:: example
            
        **Example 7.** Elements in `durations` with non-power-of-two 
        denominators result in tuplet-nested leaves: 
        
        ::

            >>> pitches = ['D5']
            >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \times 2/3 {
                    d''2
                    d''2
                    d''2
                }
            }

    ..  container:: example
            
        **Example 8.** Set `decrease_durations_monotonically` to true to 
        return nonassignable durations tied from greatest to least:

        ::

            >>> pitches = ['D#5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = leaftools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> time_signature = contexttools.TimeSignatureMark((13, 16))
            >>> time_signature = attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 13/16
                ds''2. ~
                ds''16
            }

    ..  container:: example
            
        **Example 9.** Set `decrease_durations_monotonically` to false 
        to return nonassignable durations tied from least to greatest:

        ::

            >>> pitches = ['E5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = leaftools.make_leaves(
            ...     pitches, 
            ...     durations,
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = contexttools.TimeSignatureMark((13, 16))
            >>> time_signature = attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 13/16
                e''16 ~
                e''2.
            }

    ..  container:: example
        
        **Example 10.** Set `tie_rests` to true to return tied rests for 
        nonassignable durations. Note that LilyPond does not engrave 
        ties between rests:

        ::

            >>> pitches = [None]
            >>> durations = [Duration(5, 8)]
            >>> leaves = leaftools.make_leaves(
            ...     pitches, 
            ...     durations, 
            ...     tie_rests=True,
            ...     )
            >>> staff = stafftools.RhythmicStaff(leaves)
            >>> time_signature = contexttools.TimeSignatureMark((5, 8))
            >>> time_signature = attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff {
                \time 5/8
                r2 ~
                r8
            }

    ..  container:: example
    
        **Example 11.** Set `forbidden_written_duration` to avoid notes 
        greater than or equal to a certain written duration:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = leaftools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = contexttools.TimeSignatureMark((5, 4))
            >>> time_signature = attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/4
                f'4 ~
                f'4 ~
                f'8
                g'4 ~
                g'4 ~
                g'8
            }

    ..  container:: example
        
        **Example 12.** You may set `forbidden_written_duration` and
        `decrease_durations_monotonically` together:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = leaftools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = contexttools.TimeSignatureMark((5, 4))
            >>> time_siganture = attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/4
                f'8 ~
                f'4 ~
                f'4
                g'8 ~
                g'4 ~
                g'4
            }

    Returns selection of unincorporated leaves.
    '''
    from abjad.tools import scoretools
    from abjad.tools import notetools
    from abjad.tools import resttools
    from abjad.tools import tuplettools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    # make duration pairs
    duration_pairs = [durationtools.Duration(duration) 
        for duration in durations]

    # set lists of pitches and duration pairs to the same length
    size = max(len(duration_pairs), len(pitches))
    duration_pairs = \
        sequencetools.repeat_sequence_to_length(duration_pairs, size)
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)

    Duration = durationtools.Duration
    duration_groups = \
        Duration._group_nonreduced_fractions_by_implied_prolation(
        duration_pairs)

    result = []
    for duration_group in duration_groups:
        # get factors in denominator of duration group other than 1, 2.
        factors = set(mathtools.factors(duration_group[0].denominator))
        factors.discard(1)
        factors.discard(2)
        current_pitches = pitches[0:len(duration_group)]
        pitches = pitches[len(duration_group):]
        if len(factors) == 0:
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    forbidden_written_duration=forbidden_written_duration,
                    tie_rests=tie_rests,
                    )
                result.extend(leaves)
        else:
            # compute tuplet prolation
            denominator = duration_group[0].denominator
            numerator = \
                mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / durationtools.Duration(*multiplier)
            duration_group = [ratio * durationtools.Duration(duration) 
                for duration in duration_group]
            # make tuplet leaves
            tuplet_leaves = []
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    )
                tuplet_leaves.extend(leaves)
            tuplet = tuplettools.Tuplet(multiplier, tuplet_leaves)
            result.append(tuplet)

    result = selectiontools.Selection(result)
    return result
예제 #22
0
def test_mathtools_factors_05():
    t = mathtools.factors(6)
    assert t == [1, 2, 3]
예제 #23
0
파일: make_leaves.py 프로젝트: ajyoon/abjad
def make_leaves(
    pitches,
    durations,
    decrease_durations_monotonically=True,
    forbidden_written_duration=None,
    is_diminution=True,
    metrical_hiearchy=None,
    use_messiaen_style_ties=False,
    use_multimeasure_rests=False,
    ):
    r'''Makes leaves.

    ..  container:: example

        **Example 1.** Integer and string elements in `pitches` result in
        notes:

        ::

            >>> pitches = [2, 4, 'F#5', 'G#5']
            >>> duration = Duration(1, 4)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                d'4
                e'4
                fs''4
                gs''4
            }

    ..  container:: example

        **Example 2.** Tuple elements in `pitches` result in chords:

        ::

            >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')]
            >>> duration = Duration(1, 2)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                <c' d' e'>2
                <fs'' gs'' as''>2
            }

    ..  container:: example

        **Example 3.** None-valued elements in `pitches` result in rests:

        ::

            >>> pitches = 4 * [None]
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff {
                r4
                r4
                r4
                r4
            }

    ..  container:: example

        **Example 4.** You can mix and match values passed to `pitches`:

        ::

            >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5']
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                <c' d' e'>4
                r4
                cs''4
                ds''4
            }

    ..  container:: example

        **Example 5.** Read `pitches` cyclically when the length of `pitches`
        is less than the length of `durations`:

        ::

            >>> pitches = ['C5']
            >>> durations = 2 * [Duration(3, 8), Duration(1, 8)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                c''4.
                c''8
                c''4.
                c''8
            }

    ..  container:: example

        **Example 6.** Read `durations` cyclically when the length of
        `durations` is less than the length of `pitches`:

        ::

            >>> pitches = "c'' d'' e'' f''"
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

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

    ..  container:: example

        **Example 7.** Elements in `durations` with non-power-of-two
        denominators result in tuplet-nested leaves:

        ::

            >>> pitches = ['D5']
            >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \times 2/3 {
                    d''2
                    d''2
                    d''2
                }
            }

    ..  container:: example

        **Example 8.** Set `decrease_durations_monotonically` to true to
        return nonassignable durations tied from greatest to least:

        ::

            >>> pitches = ['D#5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 13/16
                ds''2. ~
                ds''16
            }

    ..  container:: example

        **Example 9.** Set `decrease_durations_monotonically` to false
        to return nonassignable durations tied from least to greatest:

        ::

            >>> pitches = ['E5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 13/16
                e''16 ~
                e''2.
            }

    ..  container:: example

        **Example 10.** Set `forbidden_written_duration` to avoid notes
        greater than or equal to a certain written duration:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/4
                f'4 ~
                f'4 ~
                f'8
                g'4 ~
                g'4 ~
                g'8
            }

    ..  container:: example

        **Example 11.** You may set `forbidden_written_duration` and
        `decrease_durations_monotonically` together:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/4
                f'8 ~
                f'4 ~
                f'4
                g'8 ~
                g'4 ~
                g'4
            }

    ..  container:: example

        **Example 12.** Set `is_diminution` to true to produce
        diminished tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=True
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/14
                \tweak edge-height #'(0.7 . 0)
                \times 4/7 {
                    f'2 ~
                    f'8
                }
            }

        This is default behavior.

    ..  container:: example

        **Example 13.** Set `is_diminution` to false to produce
        agumented tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=False
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                \time 5/14
                \tweak text #tuplet-number::calc-fraction-text
                \tweak edge-height #'(0.7 . 0)
                \times 8/7 {
                    f'4 ~
                    f'16
                }
            }

    ..  container:: example

        **Example 14.** None-valued elements in `pitches` result in
        multimeasure rests when the multimeasure rest keyword is set:

        ::

            >>> pitches = [None]
            >>> durations = [Duration(3, 8), Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_multimeasure_rests=True,
            ...     )
            >>> leaves
            Selection(MultimeasureRest('R1 * 3/8'), MultimeasureRest('R1 * 5/8'))

        ::

            >>> staff = Staff([
            ...     Measure((3, 8), [leaves[0]]),
            ...     Measure((5, 8), [leaves[1]]),
            ...     ])
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff {
                {
                    \time 3/8
                    R1 * 3/8
                }
                {
                    \time 5/8
                    R1 * 5/8
                }
            }

    ..  container:: example

        **Example 15.** Uses Messiaen-style ties:

        ::

            >>> pitches = [0]
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_messiaen_style_ties=True,
            ...     )
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                c'2.
                c'16 \repeatTie
            }

    ..  container:: example

        **Example 16.** Works with numbered pitch-class:

        ::

            >>> pitches = [pitchtools.NumberedPitchClass(6)]
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     )
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                fs'2. ~
                fs'16
            }

    Returns selection of leaves.
    '''
    from abjad.tools import scoretools
    if isinstance(pitches, str):
        pitches = pitches.split()
    if not isinstance(pitches, list):
        pitches = [pitches]
    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]
    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions, 
        size,
        )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    duration_groups = \
        Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)
    result = []
    for duration_group in duration_groups:
        # get factors in denominator of duration group other than 1, 2.
        factors = set(mathtools.factors(duration_group[0].denominator))
        factors.discard(1)
        factors.discard(2)
        current_pitches = pitches[0:len(duration_group)]
        pitches = pitches[len(duration_group):]
        if len(factors) == 0:
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    forbidden_written_duration=forbidden_written_duration,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                result.extend(leaves)
        else:
            # compute tuplet prolation
            denominator = duration_group[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / durationtools.Duration(*multiplier)
            duration_group = [ratio * durationtools.Duration(duration)
                for duration in duration_group]
            # make tuplet leaves
            tuplet_leaves = []
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=\
                        decrease_durations_monotonically,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                tuplet_leaves.extend(leaves)
            tuplet = scoretools.Tuplet(multiplier, tuplet_leaves)
            if is_diminution and not tuplet.is_diminution:
                tuplet.toggle_prolation()
            elif not is_diminution and tuplet.is_diminution:
                tuplet.toggle_prolation()
            result.append(tuplet)
    result = selectiontools.Selection(result)
    return result
예제 #24
0
def test_mathtools_factors_03():
    t = mathtools.factors(3)
    assert t == [1, 3]
예제 #25
0
    def multiply_with_cross_cancelation(self, multiplier):
        '''Multiplies nonreduced fraction by `expr` with cross-cancelation.

        ::

            >>> fraction = mathtools.NonreducedFraction(4, 8)

        ::

            >>> fraction.multiply_with_cross_cancelation((2, 3))
            NonreducedFraction(4, 12)

        ::

            >>> fraction.multiply_with_cross_cancelation((4, 1))
            NonreducedFraction(4, 2)

        ::

            >>> fraction.multiply_with_cross_cancelation((3, 5))
            NonreducedFraction(12, 40)

        ::

            >>> fraction.multiply_with_cross_cancelation((6, 5))
            NonreducedFraction(12, 20)

        ::

            >>> fraction = mathtools.NonreducedFraction(5, 6)
            >>> fraction.multiply_with_cross_cancelation((6, 5))
            NonreducedFraction(1, 1)

        Returns nonreduced fraction.
        '''
        from abjad.tools import durationtools
        from abjad.tools import mathtools
        multiplier = durationtools.Multiplier(multiplier)
        self_numerator_factors = mathtools.factors(self.numerator)
        multiplier_denominator_factors = mathtools.factors(
            multiplier.denominator)
        for factor in multiplier_denominator_factors[:]:
            if factor in self_numerator_factors:
                self_numerator_factors.remove(factor)
                multiplier_denominator_factors.remove(factor)
        self_denominator_factors = mathtools.factors(self.denominator)
        multiplier_numerator_factors = mathtools.factors(multiplier.numerator)
        for factor in multiplier_numerator_factors[:]:
            if factor in self_denominator_factors:
                self_denominator_factors.remove(factor)
                multiplier_numerator_factors.remove(factor)
        result_numerator_factors = self_numerator_factors + \
            multiplier_numerator_factors
        result_denominator_factors = self_denominator_factors + \
            multiplier_denominator_factors
        result_numerator = 1
        for factor in result_numerator_factors:
            result_numerator *= factor
        result_denominator = 1
        for factor in result_denominator_factors:
            result_denominator *= factor
        pair = (result_numerator, result_denominator)
        return self._from_pair(pair)
예제 #26
0
def make_leaves(
    pitches,
    durations,
    decrease_durations_monotonically=True,
    forbidden_written_duration=None,
    is_diminution=True,
    metrical_hiearchy=None,
    use_messiaen_style_ties=False,
    use_multimeasure_rests=False,
):
    r'''Makes leaves.

    ..  container:: example

        **Example 1.** Integer and string elements in `pitches` result in
        notes:

        ::

            >>> pitches = [2, 4, 'F#5', 'G#5']
            >>> duration = Duration(1, 4)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                d'4
                e'4
                fs''4
                gs''4
            }

    ..  container:: example

        **Example 2.** Tuple elements in `pitches` result in chords:

        ::

            >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')]
            >>> duration = Duration(1, 2)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                <c' d' e'>2
                <fs'' gs'' as''>2
            }

    ..  container:: example

        **Example 3.** None-valued elements in `pitches` result in rests:

        ::

            >>> pitches = 4 * [None]
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new RhythmicStaff {
                r4
                r4
                r4
                r4
            }

    ..  container:: example

        **Example 4.** You can mix and match values passed to `pitches`:

        ::

            >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5']
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                <c' d' e'>4
                r4
                cs''4
                ds''4
            }

    ..  container:: example

        **Example 5.** Read `pitches` cyclically when the length of `pitches`
        is less than the length of `durations`:

        ::

            >>> pitches = ['C5']
            >>> durations = 2 * [Duration(3, 8), Duration(1, 8)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c''4.
                c''8
                c''4.
                c''8
            }

    ..  container:: example

        **Example 6.** Read `durations` cyclically when the length of
        `durations` is less than the length of `pitches`:

        ::

            >>> pitches = "c'' d'' e'' f''"
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c''4
                d''4
                e''4
                f''4
            }

    ..  container:: example

        **Example 7.** Elements in `durations` with non-power-of-two
        denominators result in tuplet-nested leaves:

        ::

            >>> pitches = ['D5']
            >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \times 2/3 {
                    d''2
                    d''2
                    d''2
                }
            }

    ..  container:: example

        **Example 8.** Set `decrease_durations_monotonically` to true to
        return nonassignable durations tied from greatest to least:

        ::

            >>> pitches = ['D#5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 13/16
                ds''2. ~
                ds''16
            }

    ..  container:: example

        **Example 9.** Set `decrease_durations_monotonically` to false
        to return nonassignable durations tied from least to greatest:

        ::

            >>> pitches = ['E5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 13/16
                e''16 ~
                e''2.
            }

    ..  container:: example

        **Example 10.** Set `forbidden_written_duration` to avoid notes
        greater than or equal to a certain written duration:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/4
                f'4 ~
                f'4 ~
                f'8
                g'4 ~
                g'4 ~
                g'8
            }

    ..  container:: example

        **Example 11.** You may set `forbidden_written_duration` and
        `decrease_durations_monotonically` together:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/4
                f'8 ~
                f'4 ~
                f'4
                g'8 ~
                g'4 ~
                g'4
            }

    ..  container:: example

        **Example 12.** Set `is_diminution` to true to produce
        diminished tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=True
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/14
                \tweak #'edge-height #'(0.7 . 0)
                \times 4/7 {
                    f'2 ~
                    f'8
                }
            }

        This is default behavior.

    ..  container:: example

        **Example 13.** Set `is_diminution` to false to produce
        agumented tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=False
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/14
                \tweak #'text #tuplet-number::calc-fraction-text
                \tweak #'edge-height #'(0.7 . 0)
                \times 8/7 {
                    f'4 ~
                    f'16
                }
            }

    ..  container:: example

        **Example 14.** None-valued elements in `pitches` result in
        multimeasure rests when the multimeasure rest keyword is set:

        ::

            >>> pitches = [None]
            >>> durations = [Duration(3, 8), Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_multimeasure_rests=True,
            ...     )
            >>> leaves
            Selection(MultimeasureRest('R1 * 3/8'), MultimeasureRest('R1 * 5/8'))

        ::

            >>> staff = Staff([
            ...     Measure((3, 8), [leaves[0]]),
            ...     Measure((5, 8), [leaves[1]]),
            ...     ])
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new RhythmicStaff {
                {
                    \time 3/8
                    R1 * 3/8
                }
                {
                    \time 5/8
                    R1 * 5/8
                }
            }

    ..  container:: example

        **Example 15.** Uses Messiaen-style ties:

        ::

            >>> pitches = [0]
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_messiaen_style_ties=True,
            ...     )
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2.
                c'16 \repeatTie
            }

    Returns selection of leaves.
    '''
    from abjad.tools import scoretools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions,
        size,
    )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    duration_groups = \
        Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    result = []
    for duration_group in duration_groups:
        # get factors in denominator of duration group other than 1, 2.
        factors = set(mathtools.factors(duration_group[0].denominator))
        factors.discard(1)
        factors.discard(2)
        current_pitches = pitches[0:len(duration_group)]
        pitches = pitches[len(duration_group):]
        if len(factors) == 0:
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=
                    decrease_durations_monotonically,
                    forbidden_written_duration=forbidden_written_duration,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                )
                result.extend(leaves)
        else:
            # compute tuplet prolation
            denominator = duration_group[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / durationtools.Duration(*multiplier)
            duration_group = [
                ratio * durationtools.Duration(duration)
                for duration in duration_group
            ]
            # make tuplet leaves
            tuplet_leaves = []
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=\
                        decrease_durations_monotonically,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                tuplet_leaves.extend(leaves)
            tuplet = scoretools.Tuplet(multiplier, tuplet_leaves)
            if is_diminution and not tuplet.is_diminution:
                tuplet.toggle_prolation()
            elif not is_diminution and tuplet.is_diminution:
                tuplet.toggle_prolation()
            result.append(tuplet)

    result = selectiontools.Selection(result)
    return result
예제 #27
0
파일: Meter.py 프로젝트: adorsk/abjad
    def __init__(self, arg=None, decrease_durations_monotonically=True):

        arg = arg or (4, 4)

        def recurse(
            node, factors, denominator, decrease_durations_monotonically):
            if factors:
                factor, factors = factors[0], factors[1:]
                preprolated_duration = node.preprolated_duration / factor
                if factor in (2, 3, 4):
                    if factors:
                        for _ in range(factor):
                            child = rhythmtreetools.RhythmTreeContainer(
                                preprolated_duration=preprolated_duration)
                            node.append(child)
                            recurse(
                                child,
                                factors,
                                denominator,
                                decrease_durations_monotonically,
                                )
                    else:
                        for _ in range(factor):
                            node.append(
                                rhythmtreetools.RhythmTreeLeaf(
                                    preprolated_duration=(1, denominator)))
                else:
                    parts = [3]
                    total = 3
                    while total < factor:
                        if decrease_durations_monotonically:
                            parts.append(2)
                        else:
                            parts.insert(0, 2)
                        total += 2
                    for part in parts:
                        grouping = rhythmtreetools.RhythmTreeContainer(
                            preprolated_duration=part * preprolated_duration)
                        if factors:
                            for _ in range(part):
                                child = rhythmtreetools.RhythmTreeContainer(
                                    preprolated_duration=preprolated_duration)
                                grouping.append(child)
                                recurse(
                                    child,
                                    factors,
                                    denominator,
                                    decrease_durations_monotonically,
                                    )
                        else:
                            for _ in range(part):
                                grouping.append(
                                    rhythmtreetools.RhythmTreeLeaf(
                                        preprolated_duration=(1, denominator)))
                        node.append(grouping)
            else:
                node.extend([rhythmtreetools.RhythmTreeLeaf(
                    preprolated_duration=(1, denominator))
                    for _ in range(node.preprolated_duration.numerator)])

        decrease_durations_monotonically = \
            bool(decrease_durations_monotonically)

        if isinstance(arg, type(self)):
            root = arg.root_node
            numerator, denominator = arg.numerator, arg.denominator
            decrease_durations_monotonically = \
                arg.decrease_durations_monotonically

        elif isinstance(arg, (str, rhythmtreetools.RhythmTreeContainer)):
            if isinstance(arg, str):
                parsed = rhythmtreetools.RhythmTreeParser()(arg)
                assert len(parsed) == 1
                root = parsed[0]
            else:
                root = arg
            for node in root.nodes:
                assert node.prolation == 1
            numerator = root.preprolated_duration.numerator
            denominator = root.preprolated_duration.denominator

        elif isinstance(arg, (tuple, scoretools.Measure)) or \
            (hasattr(arg, 'numerator') and hasattr(arg, 'denominator')):
            if isinstance(arg, tuple):
                fraction = mathtools.NonreducedFraction(arg)
            elif isinstance(arg, scoretools.Measure):
                time_signature = arg._get_effective(
                    indicatortools.TimeSignature)
                fraction = mathtools.NonreducedFraction(
                    time_signature.numerator, time_signature.denominator)
            else:
                fraction = mathtools.NonreducedFraction(
                    arg.numerator, arg.denominator)
            numerator, denominator = fraction.numerator, fraction.denominator
            factors = mathtools.factors(numerator)[1:]
            # group two nested levels of 2s into a 4
            if 1 < len(factors) and factors[0] == factors[1] == 2:
                factors[0:2] = [4]
            root = rhythmtreetools.RhythmTreeContainer(
                preprolated_duration=fraction)
            recurse(
                root,
                factors,
                denominator,
                decrease_durations_monotonically,
                )

        else:
            message = 'can not initialize {}: {!r}.'
            message = message.format(type(self).__name__, arg)
            raise ValueError(message)

        self._root_node = root
        self._numerator = numerator
        self._denominator = denominator
        self._decrease_durations_monotonically = \
            decrease_durations_monotonically
예제 #28
0
 def _split_by_duration(
     self,
     duration,
     fracture_spanners=False,
     tie_split_notes=True,
     use_messiaen_style_ties=False,
 ):
     from abjad.tools import scoretools
     from abjad.tools import selectiontools
     # check input
     duration = durationtools.Duration(duration)
     assert 0 <= duration, repr(duration)
     # if zero duration then return empty list and self
     if duration == 0:
         return [], self
     # get split point score offset
     global_split_point = self._get_timespan().start_offset + duration
     # get any duration-crossing descendents
     cross_offset = self._get_timespan().start_offset + duration
     duration_crossing_descendants = []
     for descendant in self._get_descendants():
         start_offset = descendant._get_timespan().start_offset
         stop_offset = descendant._get_timespan().stop_offset
         if start_offset < cross_offset < stop_offset:
             duration_crossing_descendants.append(descendant)
     # get any duration-crossing measure descendents
     measures = [
         x for x in duration_crossing_descendants
         if isinstance(x, scoretools.Measure)
     ]
     # if we must split a power-of-two measure at non-power-of-two
     # split point then go ahead and transform the power-of-two measure
     # to non-power-of-two equivalent now;
     # code that crawls and splits later on will be happier
     if len(measures) == 1:
         measure = measures[0]
         split_point_in_measure = \
             global_split_point - measure._get_timespan().start_offset
         if measure.has_non_power_of_two_denominator:
             if not measure.implied_prolation == \
                 split_point_in_measure.implied_prolation:
                 raise NotImplementedError
         elif not mathtools.is_nonnegative_integer_power_of_two(
                 split_point_in_measure.denominator):
             non_power_of_two_factors = mathtools.remove_powers_of_two(
                 split_point_in_measure.denominator)
             non_power_of_two_factors = mathtools.factors(
                 non_power_of_two_factors)
             non_power_of_two_product = 1
             for non_power_of_two_factor in non_power_of_two_factors:
                 non_power_of_two_product *= non_power_of_two_factor
             scoretools.scale_measure_denominator_and_adjust_measure_contents(
                 measure, non_power_of_two_product)
             # rederive duration crosses with possibly new measure contents
             cross_offset = self._get_timespan().start_offset + duration
             duration_crossing_descendants = []
             for descendant in self._get_descendants():
                 start_offset = descendant._get_timespan().start_offset
                 stop_offset = descendant._get_timespan().stop_offset
                 if start_offset < cross_offset < stop_offset:
                     duration_crossing_descendants.append(descendant)
     elif 1 < len(measures):
         message = 'measures can not nest.'
         raise Exception(message)
     # 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, scoretools.Leaf):
         assert isinstance(bottom, scoretools.Leaf)
         did_split_leaf = True
         split_point_in_bottom = \
             global_split_point - bottom._get_timespan().start_offset
         left_list, right_list = bottom._split_by_duration(
             split_point_in_bottom,
             fracture_spanners=fracture_spanners,
             tie_split_notes=tie_split_notes,
             use_messiaen_style_ties=use_messiaen_style_ties,
         )
         right = right_list[0]
         leaf_right_of_split = right
         leaf_left_of_split = left_list[-1]
         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).by_class(scoretools.Leaf):
             if leaf._get_timespan().start_offset == global_split_point:
                 leaf_right_of_split = leaf
                 leaf_left_of_split = leaf_right_of_split._get_leaf(-1)
                 break
         else:
             message = 'can not split empty container {!r}.'
             message = message.format(bottom)
             raise Exception(message)
     # find component to right of split that is also immediate child of
     # last duration-crossing container
     for component in \
         leaf_right_of_split._get_parentage(include_self=True):
         if component._parent is duration_crossing_containers[-1]:
             highest_level_component_right_of_split = component
             break
     else:
         message = 'should we be able to get here?'
         raise ValueError(message)
     # crawl back up through duration-crossing containers and
     # fracture spanners if requested
     if fracture_spanners:
         start_offset = leaf_right_of_split._get_timespan().start_offset
         for parent in leaf_right_of_split._get_parentage():
             if parent._get_timespan().start_offset == start_offset:
                 for spanner in parent._get_spanners():
                     index = spanner._index(parent)
                     spanner._fracture(index, direction=Left)
             if parent is component:
                 break
     # crawl back up through duration-crossing containers and split each
     previous = highest_level_component_right_of_split
     for duration_crossing_container in \
         reversed(duration_crossing_containers):
         assert isinstance(duration_crossing_container,
                           scoretools.Container)
         i = duration_crossing_container.index(previous)
         left, right = duration_crossing_container._split_at_index(
             i,
             fracture_spanners=fracture_spanners,
         )
         previous = right
     # NOTE: If logical tie here is convenience, then fusing is good.
     #       If logical tie here is user-given, then fusing is less good.
     #       Maybe later model difference between user logical ties and not.
     left_logical_tie = leaf_left_of_split._get_logical_tie()
     right_logical_tie = leaf_right_of_split._get_logical_tie()
     left_logical_tie._fuse_leaves_by_immediate_parent()
     right_logical_tie._fuse_leaves_by_immediate_parent()
     # 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, scoretools.Note)):
             if (leaf_left_of_split._get_parentage().root is
                     leaf_right_of_split._get_parentage().root):
                 leaves_around_split = \
                     (leaf_left_of_split, leaf_right_of_split)
                 selection = selectiontools.ContiguousSelection(
                     leaves_around_split)
                 selection._attach_tie_spanner_to_leaf_pair(
                     use_messiaen_style_ties=use_messiaen_style_ties, )
     # return pair of left and right list-wrapped halves of container
     return ([left], [right])
예제 #29
0
파일: make_notes.py 프로젝트: odub/abjad
def make_notes(
    pitches, 
    durations, 
    decrease_durations_monotonically=True,
    use_messiaen_style_ties=False,
    ):
    r'''Makes notes according to `pitches` and `durations`.


    ..  container:: example

        **Example 1.** Cycles through `pitches` when the length of `pitches` is
        less than the length of `durations`:

        ::

            >>> notes = scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)])
            >>> notes
            Selection(Note("c'16"), Note("c'8"), Note("c'8"))
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16
                c'8
                c'8
            }

    ..  container:: example

        **Example 2.** Cycles through `durations` when the length of `durations`
        is less than the length of `pitches`:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0, 2, 4, 5, 7],
            ...     [(1, 16), (1, 8), (1, 8)],
            ...     )
            >>> notes
            Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8"))
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

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

    ..  container:: example

        **Example 3.** Creates ad hoc tuplets for nonassignable durations:

        ::

            >>> notes = scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)])
            >>> notes
            Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8"))
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16
                \tweak #'edge-height #'(0.7 . 0)
                \times 2/3 {
                    c'8
                }
                c'8
            }

    ..  container:: example

        **Example 4.** Set ``decrease_durations_monotonically=True`` to express
        tied values in decreasing duration:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     decrease_durations_monotonically=True,
            ...     )
            >>> notes
            Selection(Note("c'2."), Note("c'16"))
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2. ~
                c'16
            }

    ..  container:: example

        **Example 5.** Set ``decrease_durations_monotonically=False`` to
        express tied values in increasing duration:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> notes
            Selection(Note("c'16"), Note("c'2."))
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16 ~
                c'2.
            }

    ..  container:: example

        **Example 6.** Uses Messiaen-style ties:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     use_messiaen_style_ties=True,
            ...     )
            >>> staff = Staff(notes)

        ::

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

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2.
                c'16 \repeatTie
            }

    Set `pitches` to a single pitch or a sequence of pitches.

    Set `durations` to a single duration or a list of durations.

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

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions, 
        size,
        )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    durations = Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    def _make_unprolated_notes(
        pitches,
        durations,
        decrease_durations_monotonically=decrease_durations_monotonically,
        use_messiaen_style_ties=False,
        ):
        assert len(pitches) == len(durations)
        result = []
        for pitch, duration in zip(pitches, durations):
            result.extend(
                scoretools.make_tied_leaf(
                    scoretools.Note,
                    duration,
                    pitches=pitch,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                )
        return result

    result = []
    for duration in durations:
        # get factors in denominator of duration group duration not 1 or 2
        factors = set(mathtools.factors(duration[0].denominator))
        factors.discard(1)
        factors.discard(2)
        ps = pitches[0:len(duration)]
        pitches = pitches[len(duration):]
        if len(factors) == 0:
            result.extend(
                _make_unprolated_notes(
                    ps,
                    duration,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                )
        else:
            # compute prolation
            denominator = duration[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / fractions.Fraction(*multiplier)
            duration = [ratio * durationtools.Duration(d) for d in duration]
            ns = _make_unprolated_notes(
                ps,
                duration,
                decrease_durations_monotonically=decrease_durations_monotonically,
                use_messiaen_style_ties=use_messiaen_style_ties,
                )
            t = scoretools.Tuplet(multiplier, ns)
            result.append(t)

    # return result
    result = selectiontools.Selection(result)
    return result
예제 #30
0
def test_mathtools_factors_02():
    t = mathtools.factors(2)
    assert t == [1, 2]