def test_mathtools_remove_powers_of_two_01():
    r'''Remove powers of two from integer n.
    '''

    assert mathtools.remove_powers_of_two(10) == 5
    assert mathtools.remove_powers_of_two(20) == 5
    assert mathtools.remove_powers_of_two(30) == 15
    assert mathtools.remove_powers_of_two(40) == 5
    assert mathtools.remove_powers_of_two(50) == 25
    assert mathtools.remove_powers_of_two(60) == 15
    assert mathtools.remove_powers_of_two(70) == 35
    assert mathtools.remove_powers_of_two(80) == 5
    assert mathtools.remove_powers_of_two(90) == 45
Example #2
0
def move_full_measure_tuplet_prolation_to_measure_time_signature(expr):
    r'''Moves prolation of full-measure tuplet to time signature of measure.

    Measures usually become non-power-of-two as as result.

    ..  container:: example

        ::

            >>> tuplet = scoretools.FixedDurationTuplet(Duration(2, 8), "c'8 d'8 e'8")
            >>> measure = Measure((2, 8), [tuplet])
            >>> measure.implicit_scaling = True
            >>> scoretools.move_full_measure_tuplet_prolation_to_measure_time_signature(measure)

        ..  doctest::

            >>> print(format(measure))
            {
                \time 3/12
                \scaleDurations #'(2 . 3) {
                    c'8
                    d'8
                    e'8
                }
            }

    Returns none.
    '''
    from abjad.tools import indicatortools
    from abjad.tools import scoretools

    for measure in iterate(expr).by_class(scoretools.Measure):
        if len(measure) == 1:
            if isinstance(measure[0], scoretools.Tuplet):
                tuplet = measure[0]
                tuplet_multiplier = tuplet.multiplier
                tuplet_denominator = tuplet_multiplier.denominator
                reduced_denominator = mathtools.remove_powers_of_two(
                    tuplet_denominator)
                time_signature = measure.time_signature
                time_signature_rational = durationtools.Duration(
                    time_signature.numerator, time_signature.denominator)
                numerator = time_signature_rational.numerator * reduced_denominator
                denominator = time_signature_rational.denominator * reduced_denominator
                time_signature = indicatortools.TimeSignature(
                    (numerator, denominator))
                detach(indicatortools.TimeSignature, measure)
                attach(time_signature, measure)
                if time_signature.has_non_power_of_two_denominator:
                    measure.implicit_scaling = True
                time_signature_multiplier = \
                    measure.time_signature.implied_prolation
                written_adjustment = tuplet_multiplier.__div__(
                    time_signature_multiplier)
                tuplet._extract()
                measure._scale_contents(written_adjustment)
def move_full_measure_tuplet_prolation_to_measure_time_signature(expr):
    r'''Moves prolation of full-measure tuplet to time signature of measure.

    Measures usually become non-power-of-two as as result.

    ..  container:: example

        ::

            >>> tuplet = scoretools.FixedDurationTuplet(Duration(2, 8), "c'8 d'8 e'8")
            >>> measure = Measure((2, 8), [tuplet])
            >>> measure.implicit_scaling = True
            >>> scoretools.move_full_measure_tuplet_prolation_to_measure_time_signature(measure)

        ..  doctest::

            >>> print format(measure)
            {
                \time 3/12
                \scaleDurations #'(2 . 3) {
                    c'8
                    d'8
                    e'8
                }
            }

    Returns none.
    '''
    from abjad.tools import indicatortools
    from abjad.tools import scoretools

    for measure in iterate(expr).by_class(scoretools.Measure):
        if len(measure) == 1:
            if isinstance(measure[0], scoretools.Tuplet):
                tuplet = measure[0]
                tuplet_multiplier = tuplet.multiplier
                tuplet_denominator = tuplet_multiplier.denominator
                reduced_denominator = mathtools.remove_powers_of_two(tuplet_denominator)
                time_signature = measure.time_signature
                time_signature_rational = durationtools.Duration(
                    time_signature.numerator, time_signature.denominator)
                numerator = time_signature_rational.numerator * reduced_denominator
                denominator = time_signature_rational.denominator * reduced_denominator
                time_signature = indicatortools.TimeSignature((numerator, denominator))
                detach(indicatortools.TimeSignature, measure)
                attach(time_signature, measure)
                if time_signature.has_non_power_of_two_denominator:
                    measure.implicit_scaling = True
                time_signature_multiplier = \
                    measure.time_signature.implied_prolation
                written_adjustment = tuplet_multiplier / time_signature_multiplier
                tuplet._extract()
                measure._scale_contents(written_adjustment)
Example #4
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])
Example #5
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])