Esempio n. 1
0
    def _notate(self, 
        grace_handler, attack_point_optimizer, attach_tempo_marks):
        voice = scoretools.Voice()

        # generate the first
        beat = self.items[0]
        components = beat.q_grid(beat.beatspan)
        if attach_tempo_marks:
            attachment_target = components[0]
            if isinstance(attachment_target, containertools.Container):
                attachment_target = attachment_target.select_leaves()[0]
            tempo = copy.copy(beat.tempo)
            attach(tempo, attachment_target)
        voice.extend(components)

        # generate the rest pairwise, comparing tempi
        for beat_one, beat_two in \
            sequencetools.iterate_sequence_pairwise_strict(self.items):
            components = beat_two.q_grid(beat_two.beatspan)
            if (beat_two.tempo != beat_one.tempo) and attach_tempo_marks:
                attachment_target = components[0]
                if isinstance(attachment_target, containertools.Container):
                    attachment_target = attachment_target.select_leaves()[0]
                tempo = copy.copy(beat_two.tempo)
                attach(tempo, attachment_target)
            voice.extend(components)

        # apply tie chains, pitches, grace containers
        self._notate_leaves_pairwise(voice, grace_handler)

        # partition tie chains in voice
        attack_point_optimizer(voice)

        return voice
Esempio n. 2
0
 def _shift_downbeat_q_events_to_next_q_grid(self):
     beats = self.beats
     for one, two in sequencetools.iterate_sequence_pairwise_strict(beats):
         one_q_events = one.q_grid.next_downbeat.q_event_proxies
         two_q_events = two.q_grid.leaves[0].q_event_proxies
         while one_q_events:
             two_q_events.append(one_q_events.pop())
Esempio n. 3
0
    def _find_divisible_leaf_indices_and_subdivisions(self, q_grid):
        # TODO: This should actually check for all QEvents which fall 
        # within the leaf's duration,
        # including QEvents attached to the next leaf
        # It may be prudent to actually store QEvents in two lists: 
        # before_offset and after_offset
        indices, subdivisions = [], []

        leaves = q_grid.leaves
        i = 0
        for leaf_one, leaf_two in \
            sequencetools.iterate_sequence_pairwise_strict(leaves):
            if (leaf_one.succeeding_q_event_proxies or 
                leaf_two.preceding_q_event_proxies) and \
                leaf_one.is_divisible:
                if len(leaf_one.q_event_proxies) == 1 and \
                    leaf_one.q_event_proxies[0].offset == \
                        leaf_one.start_offset:
                    pass # perfect match, don't bother to continue subdivision
                else:
                    parentage_ratios = leaf_one.parentage_ratios
                    leaf_subdivisions = \
                        self._find_leaf_subdivisions(parentage_ratios)
                    if leaf_subdivisions:
                        indices.append(i)
                        subdivisions.append(tuple(leaf_subdivisions))
            i += 1
        return indices, subdivisions
Esempio n. 4
0
 def has_voice_crossing(self):
     for upper, lower in \
         sequencetools.iterate_sequence_pairwise_strict(self.cells):
         for lower_pitch in lower.pitches:
             for upper_pitch in upper.pitches:
                 if upper_pitch.numbered_pitch < \
                     lower_pitch.numbered_pitch:
                     return True
     return False
Esempio n. 5
0
    def list_nonspanning_subarrays(self):
        r'''Lists nonspanning subarrays of pitch array.

        ::

            >>> array = pitcharraytools.PitchArray([
            ...     [2, 2, 3, 1],
            ...     [1, 2, 1, 1, 2, 1],
            ...     [1, 1, 1, 1, 1, 1, 1, 1]])
            >>> print array
            [     ] [     ] [         ] [ ]
            [ ] [     ] [ ] [ ] [     ] [ ]
            [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]

        ::

            >>> subarrays = array.list_nonspanning_subarrays()
            >>> len(subarrays)
            3

        ::

            >>> print subarrays[0]
            [     ] [     ]
            [ ] [     ] [ ]
            [ ] [ ] [ ] [ ]

        ::

            >>> print subarrays[1]
            [         ]
            [ ] [     ]
            [ ] [ ] [ ]

        ::

            >>> print subarrays[2]
            [ ]
            [ ]
            [ ]

        Returns list.
        '''
        unspanned_indices = []
        for i in range(self.width + 1):
            if not self.has_spanning_cell_over_index(i):
                unspanned_indices.append(i)
        array_depth = self.depth
        subarrays = []
        for start_column, stop_column in \
            sequencetools.iterate_sequence_pairwise_strict(unspanned_indices):
            upper_left_pair = (0, start_column)
            lower_right_pair = (array_depth, stop_column)
            subarray = self.copy_subarray(upper_left_pair, lower_right_pair)
            subarrays.append(subarray)
        return subarrays
Esempio n. 6
0
 def graph_order(self):
     r'''Graph order of tree node.
     
     Returns tuple.
     '''
     from abjad.tools import sequencetools
     order = []
     for parent, child in sequencetools.iterate_sequence_pairwise_strict(
         reversed(self.improper_parentage)):
         order.append(parent.index(child))
     return tuple(order)
Esempio n. 7
0
    def prolations(self):
        r'''Prolations of rhythm tree node.

        Returns tuple.
        '''
        prolations = [durationtools.Multiplier(1)]
        improper_parentage = self.improper_parentage
        for child, parent in \
            sequencetools.iterate_sequence_pairwise_strict(improper_parentage):
            prolations.append(durationtools.Multiplier(
                parent.preprolated_duration, parent._contents_duration))
        return tuple(prolations)
Esempio n. 8
0
 def get_offsets_at_depth(depth):
     if depth < len(offset_inventory):
         return offset_inventory[depth]
     while len(offset_inventory) <= depth:
         new_offsets = []
         old_offsets = offset_inventory[-1]
         for first, second in \
             sequencetools.iterate_sequence_pairwise_strict(old_offsets):
             new_offsets.append(first)
             new_offsets.append((first + second) / 2)
         new_offsets.append(old_offsets[-1])
         offset_inventory.append(tuple(new_offsets))
     return offset_inventory[depth]
Esempio n. 9
0
    def has_voice_crossing(self):
        r'''Is true when pitch array column has voice crossing. Otherwise false.

        Returns boolean.
        '''
        for upper, lower in \
            sequencetools.iterate_sequence_pairwise_strict(self.cells):
            for lower_pitch in lower.pitches:
                for upper_pitch in upper.pitches:
                    if upper_pitch.numbered_pitch < \
                        lower_pitch.numbered_pitch:
                        return True
        return False
def _get_intervals_in_subrun(subrun_source):
    from abjad.tools import pitchtools

    subrun_source = list(subrun_source)
    result = [0]
    for first, second in sequencetools.iterate_sequence_pairwise_strict(
        subrun_source):
        first_pitch = pitchtools.get_named_pitch_from_pitch_carrier(first)
        second_pitch = pitchtools.get_named_pitch_from_pitch_carrier(second)
        interval = abs(pitchtools.NumberedPitch(second_pitch)) - \
            abs(pitchtools.NumberedPitch(first_pitch))
        result.append(interval + result[-1])
    result.pop(0)
    return result
def cumulative_sums_pairwise(sequence):
    r'''Lists pairwise cumulative sums of `sequence` from ``0``.

    ::

        >>> mathtools.cumulative_sums_pairwise([1, 2, 3, 4, 5, 6])
        [(0, 1), (1, 3), (3, 6), (6, 10), (10, 15), (15, 21)]

    Returns list of pairs.
    '''
    from abjad.tools import mathtools
    from abjad.tools import sequencetools

    return list(sequencetools.iterate_sequence_pairwise_strict(mathtools.cumulative_sums(sequence)))
Esempio n. 12
0
    def _interleave_source_with_code_blocks(
        self,
        tmp_directory,
        lines,
        code_blocks,
        output_format,
        ):

        #print 'INTERLEAVE SOURCE WITH CODE BLOCKS'
        image_file_names = [x for x in os.listdir(tmp_directory)
            if (x.endswith(output_format.image_format) and
               x.startswith(self.image_prefix))]

        image_dict = {}
        for image_file_name in image_file_names:
            suffix = os.path.splitext(image_file_name.partition('-')[2])[0]
            index, part, page = suffix.partition('-')
            index = int(index)
            if page:
                page = int(page.strip('page'))
            else:
                page = 0
            if index not in image_dict:
                image_dict[index] = {}
            image_dict[index][page] = image_file_name

        interleaved = []
        interleaved.append(
            '\n'.join(lines[:code_blocks[0].starting_line_number]))
        for pair in sequencetools.iterate_sequence_pairwise_strict(
            code_blocks):
            first_block, second_block = pair
            interleaved.extend(output_format(first_block, image_dict))
            interleaved.append('\n'.join(lines[
                first_block.ending_line_number+1:
                second_block.starting_line_number]))

        interleaved.extend(output_format(code_blocks[-1], image_dict))
        interleaved.append('\n'.join(
            lines[code_blocks[-1].ending_line_number+1:]))
        return '\n'.join(interleaved)
Esempio n. 13
0
    def _notate(
        self,
        grace_handler,
        attack_point_optimizer,
        attach_tempos,
        ):
        voice = scoretools.Voice()

        # generate the first
        q_target_measure = self.items[0]
        measure = scoretools.Measure(q_target_measure.time_signature)
        for beat in q_target_measure.beats:
            measure.extend(beat.q_grid(beat.beatspan))
        if attach_tempos:
            tempo = copy.copy(q_target_measure.tempo)
            attach(tempo, measure)
        voice.append(measure)

        # generate the rest pairwise, comparing tempi
        for q_target_measure_one, q_target_measure_two in \
            sequencetools.iterate_sequence_pairwise_strict(self.items):
            measure = scoretools.Measure(q_target_measure_two.time_signature)
            for beat in q_target_measure_two.beats:
                measure.extend(beat.q_grid(beat.beatspan))
            if (q_target_measure_two.tempo != q_target_measure_one.tempo) \
                and attach_tempos:
                tempo = copy.copy(q_target_measure_two.tempo)
                attach(tempo, measure)
            voice.append(measure)

        # apply logical ties, pitches, grace containers
        self._notate_leaves_pairwise(voice, grace_handler)

        # partition logical ties in each measure
        for measure in voice:
            attack_point_optimizer(measure)

        return voice
def iterate_leaf_pairs_in_expr(expr):
    r'''Iterate leaf pairs forward in `expr`:

    ::

        >>> score = Score([])
        >>> notes = [Note("c'8"), Note("d'8"), Note("e'8"), Note("f'8"), Note("g'4")]
        >>> score.append(Staff(notes))
        >>> notes = [Note(x, (1, 4)) for x in [-12, -15, -17]]
        >>> score.append(Staff(notes))
        >>> clef = contexttools.ClefMark('bass')
        >>> attach(clef, score[1])
        ClefMark('bass')(Staff{3})
        >>> show(score) # doctest: +SKIP

    ..  doctest::

        >>> f(score)
        \new Score <<
            \new Staff {
                c'8
                d'8
                e'8
                f'8
                g'4
            }
            \new Staff {
                \clef "bass"
                c4
                a,4
                g,4
            }
        >>

    ::

        >>> for pair in iterationtools.iterate_leaf_pairs_in_expr(score):
        ...        pair
        (Note("c'8"), Note('c4'))
        (Note("c'8"), Note("d'8"))
        (Note('c4'), Note("d'8"))
        (Note("d'8"), Note("e'8"))
        (Note("d'8"), Note('a,4'))
        (Note('c4'), Note("e'8"))
        (Note('c4'), Note('a,4'))
        (Note("e'8"), Note('a,4'))
        (Note("e'8"), Note("f'8"))
        (Note('a,4'), Note("f'8"))
        (Note("f'8"), Note("g'4"))
        (Note("f'8"), Note('g,4'))
        (Note('a,4'), Note("g'4"))
        (Note('a,4'), Note('g,4'))
        (Note("g'4"), Note('g,4'))

    Iterate leaf pairs left-to-right and top-to-bottom.

    Returns generator.
    '''
    from abjad.tools import iterationtools

    vertical_moments = iterationtools.iterate_vertical_moments_in_expr(expr)
    for moment_1, moment_2 in \
        sequencetools.iterate_sequence_pairwise_strict(vertical_moments):
        for pair in sequencetools.yield_all_unordered_pairs_of_sequence(
            moment_1.start_leaves):
            yield pair
        pairs = sequencetools.yield_all_pairs_between_sequences(
            moment_1.leaves, moment_2.start_leaves)
        for pair in pairs:
            yield pair
    else:
        for pair in sequencetools.yield_all_unordered_pairs_of_sequence(
            moment_2.start_leaves):
            yield pair
Esempio n. 15
0
    def generate_offset_kernel_to_denominator(
        self, 
        denominator, 
        normalize=True,
        ):
        r'''Generate a dictionary of all offsets in a meter up
        to `denominator`, where the keys are the offsets and the values
        are the normalized weights of those offsets:

        ::

            >>> meter = \
            ...     metertools.Meter((4, 4))
            >>> kernel = \
            ...     meter.generate_offset_kernel_to_denominator(8)
            >>> for offset, weight in sorted(kernel.kernel.iteritems()):
            ...     print '{!s}\t{!s}'.format(offset, weight)
            ...
            0       3/16
            1/8     1/16
            1/4     1/8
            3/8     1/16
            1/2     1/8
            5/8     1/16
            3/4     1/8
            7/8     1/16
            1       3/16

        This is useful for testing how strongly a collection of offsets
        responds to a given meter.

        Returns dictionary.
        '''
        from abjad.tools import metertools
        assert mathtools.is_positive_integer_power_of_two(
            denominator / self.denominator)

        inventory = list(self.depthwise_offset_inventory)
        old_flag_count = durationtools.Duration(1, self.denominator).flag_count
        new_flag_count = durationtools.Duration(1, denominator).flag_count
        extra_depth = new_flag_count - old_flag_count
        for _ in range(extra_depth):
            old_offsets = inventory[-1]
            new_offsets = []
            for first, second in \
                sequencetools.iterate_sequence_pairwise_strict(old_offsets):
                new_offsets.append(first)
                new_offsets.append((first + second) / 2)
            new_offsets.append(old_offsets[-1])
            inventory.append(tuple(new_offsets))

        total = 0
        kernel = {}
        for offsets in inventory:
            for offset in offsets:
                if offset not in kernel:
                    kernel[offset] = 0
                kernel[offset] += 1
                total += 1

        if normalize:
            for offset, response in kernel.iteritems():
                kernel[offset] = durationtools.Multiplier(response, total)

        return metertools.MetricAccentKernel(kernel)
def list_numbered_interval_numbers_pairwise(pitch_carriers, wrap=False):
    r'''List numbered interval numbers pairwise between `pitch_carriers`:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8 g'8 a'8 b'8 c''8")

    ..  doctest::

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

    ::

        >>> pitchtools.list_numbered_interval_numbers_pairwise(
        ... staff)
        [2, 2, 1, 2, 2, 2, 1]

    ::

        >>> pitchtools.list_numbered_interval_numbers_pairwise(
        ... staff, wrap=True)
        [2, 2, 1, 2, 2, 2, 1, -12]

    ::

        >>> notes = [
        ...     Note("c'8"), Note("d'8"), Note("e'8"), Note("f'8"),
        ...     Note("g'8"), Note("a'8"), Note("b'8"), Note("c''8")]

    ::

        >>> notes.reverse()

    ::

        >>> pitchtools.list_numbered_interval_numbers_pairwise(
        ... notes)
        [-1, -2, -2, -2, -1, -2, -2]

    ::

        >>> pitchtools.list_numbered_interval_numbers_pairwise(
        ... notes, wrap=True)
        [-1, -2, -2, -2, -1, -2, -2, 12]

    When ``wrap = False`` do not return ``pitch_carriers[-1] - pitch_carriers[0]``
    as last in series.

    When ``wrap = True`` do return ``pitch_carriers[-1] - pitch_carriers[0]``
    as last in series.

    Returns list.
    '''
    from abjad.tools import pitchtools

    result = []

    if len(pitch_carriers) == 0:
        return result
    elif len(pitch_carriers) == 1:
        if pitchtools.Pitch.is_pitch_carrier(pitch_carriers[0]):
            return result
        else:
            message = 'must be pitch, not, note-head or chord.'
            raise TypeError(message)

    if wrap:
        pairs = sequencetools.iterate_sequence_pairwise_wrapped(pitch_carriers)
    else:
        pairs = sequencetools.iterate_sequence_pairwise_strict(pitch_carriers)

    for first_carrier, second_carrier in pairs:
        first_pitch = pitchtools.get_named_pitch_from_pitch_carrier(first_carrier)
        second_pitch = pitchtools.get_named_pitch_from_pitch_carrier(second_carrier)
        signed_interval = abs(pitchtools.NumberedPitch(second_pitch)) - \
            abs(pitchtools.NumberedPitch(first_pitch))
        result.append(signed_interval)

    return result
Esempio n. 17
0
 def graph_order(self):
     order = []
     for parent, child in sequencetools.iterate_sequence_pairwise_strict(
         reversed(self.improper_parentage)):
         order.append(parent.index(child))
     return tuple(order)
    def compute_depth(self, bounding_interval=None):
        r"""Compute a tree whose intervals represent the level of overlap
        of the time interval aggregate:

        ::

            >>> a = timeintervaltools.TimeInterval(0, 3)
            >>> b = timeintervaltools.TimeInterval(6, 12)
            >>> c = timeintervaltools.TimeInterval(9, 15)
            >>> tree = timeintervaltools.TimeIntervalTree([a, b, c])
            >>> tree.compute_depth()
            TimeIntervalTree([
                TimeInterval(Offset(0, 1), Offset(3, 1), {'depth': 1}),
                TimeInterval(Offset(3, 1), Offset(6, 1), {'depth': 0}),
                TimeInterval(Offset(6, 1), Offset(9, 1), {'depth': 1}),
                TimeInterval(Offset(9, 1), Offset(12, 1), {'depth': 2}),
                TimeInterval(Offset(12, 1), Offset(15, 1), {'depth': 1})
            ])

        If `bounding_interval` is not none, only consider the depth of 
        time intervals which intersect that time interval:

        ::

            >>> a = timeintervaltools.TimeInterval(0, 3)
            >>> b = timeintervaltools.TimeInterval(6, 12)
            >>> c = timeintervaltools.TimeInterval(9, 15)
            >>> tree = timeintervaltools.TimeIntervalTree([a, b, c])
            >>> d = timeintervaltools.TimeInterval(-1, 16)
            >>> tree.compute_depth(bounding_interval=d)
            TimeIntervalTree([
                TimeInterval(Offset(-1, 1), Offset(0, 1), {'depth': 0}),
                TimeInterval(Offset(0, 1), Offset(3, 1), {'depth': 1}),
                TimeInterval(Offset(3, 1), Offset(6, 1), {'depth': 0}),
                TimeInterval(Offset(6, 1), Offset(9, 1), {'depth': 1}),
                TimeInterval(Offset(9, 1), Offset(12, 1), {'depth': 2}),
                TimeInterval(Offset(12, 1), Offset(15, 1), {'depth': 1}),
                TimeInterval(Offset(15, 1), Offset(16, 1), {'depth': 0})
            ])
            
        Returns interval tree.
        """
        from abjad.tools import sequencetools
        from abjad.tools import timeintervaltools

        if bounding_interval is not None:
            bounded_tree = self.find_intervals_intersecting_or_tangent_to_interval(bounding_interval)
            if not bounded_tree:
                return timeintervaltools.TimeIntervalTree(
                    [
                        timeintervaltools.TimeInterval(
                            bounding_interval.start_offset, bounding_interval.stop_offset, {"depth": 0}
                        )
                    ]
                )
            all_bounds = list(bounded_tree.all_unique_bounds)
            while all_bounds[0] < bounding_interval.start_offset:
                all_bounds.pop(0)
            while bounding_interval.stop_offset < all_bounds[-1]:
                all_bounds.pop()
            if bounding_interval.start_offset < all_bounds[0]:
                all_bounds.insert(0, bounding_interval.start_offset)
            if all_bounds[-1] < bounding_interval.stop_offset:
                all_bounds.append(bounding_interval.stop_offset)
        else:
            all_bounds = list(self.all_unique_bounds)
        depth_intervals = []
        for start_offset, stop_offset in sequencetools.iterate_sequence_pairwise_strict(all_bounds):
            current_interval = timeintervaltools.TimeInterval(start_offset, stop_offset, {})
            found = self.find_intervals_intersecting_or_tangent_to_interval(current_interval)
            depth = 0
            if found:
                depth = len(
                    [
                        x
                        for x in found
                        if (
                            not x.start_offset == current_interval.stop_offset
                            and not x.stop_offset == current_interval.start_offset
                        )
                    ]
                )
            current_interval["depth"] = depth
            depth_intervals.append(current_interval)
        return timeintervaltools.TimeIntervalTree(depth_intervals)
Esempio n. 19
0
 def _split(
     self,
     durations,
     cyclic=False,
     fracture_spanners=False,
     tie_split_notes=True,
     ):
     from abjad.tools import iterationtools
     from abjad.tools import pitchtools
     from abjad.tools import selectiontools
     from abjad.tools import spannertools
     durations = [durationtools.Duration(x) for x in durations]
     if cyclic:
         durations = sequencetools.repeat_sequence_to_weight_exactly(
             durations, self._get_duration())
     durations = [durationtools.Duration(x) for x in durations]
     if sum(durations) < self._get_duration():
         last_duration = self._get_duration() - sum(durations)
         durations.append(last_duration)
     sequencetools.truncate_sequence_to_weight(
         durations, self._get_duration())
     result = []
     leaf_prolation = self._get_parentage(include_self=False).prolation
     leaf_copy = copy.copy(self)
     for duration in durations:
         new_leaf = copy.copy(self)
         preprolated_duration = duration / leaf_prolation
         shard = new_leaf._set_duration(preprolated_duration)
         shard = [x._get_parentage().root for x in shard]
         result.append(shard)
     flattened_result = sequencetools.flatten_sequence(result)
     flattened_result = selectiontools.SliceSelection(flattened_result)
     spanner_classes = (spannertools.TieSpanner,)
     parentage = self._get_parentage()
     if parentage._get_spanners(spanner_classes=spanner_classes):
         selection = selectiontools.select(flattened_result)
         for component in selection:
             for mark in component._get_spanners(
                 spanner_classes=spanner_classes):
                 mark.detach()
     # replace leaf with flattened result
     selection = selectiontools.SliceSelection(self)
     parent, start, stop = selection._get_parent_and_start_stop_indices()
     if parent:
         parent.__setitem__(slice(start, stop + 1), flattened_result)
     else:
         selection._give_dominant_spanners(flattened_result)
         selection._withdraw_from_crossing_spanners()
     # fracture spanners
     if fracture_spanners:
         first_shard = result[0]
         for spanner in first_shard[-1]._get_spanners():
             index = spanner.index(first_shard[-1])
             spanner.fracture(index, direction=Right)
         last_shard = result[-1]
         for spanner in last_shard[0]._get_spanners():
             index = spanner.index(last_shard[0])
             spanner.fracture(index, direction=Left)
         for middle_shard in result[1:-1]:
             for spanner in middle_shard[0]._get_spanners():
                 index = spanner.index(middle_shard[0])
                 spanner.fracture(index, direction=Left)
             for spanner in middle_shard[-1]._get_spanners():
                 index = spanner.index(middle_shard[-1])
                 spanner.fracture(index, direction=Right)
     # adjust first leaf
     first_leaf = flattened_result[0]
     self._detach_grace_containers(kind='after')
     # adjust any middle leaves
     for middle_leaf in flattened_result[1:-1]:
         middle_leaf._detach_grace_containers(kind='grace')
         self._detach_grace_containers(kind='after')
         for mark in middle_leaf._get_marks():
             mark.detach()
     # adjust last leaf
     last_leaf = flattened_result[-1]
     last_leaf._detach_grace_containers(kind='grace')
     for mark in last_leaf._get_marks():
         mark.detach()
     # tie split notes, rests and chords as specified
     if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes:
         flattened_result_leaves = iterationtools.iterate_leaves_in_expr(
             flattened_result)
         # TODO: implement SliceSelection._attach_tie_spanner_to_leaves()
         for leaf_pair in sequencetools.iterate_sequence_pairwise_strict(
             flattened_result_leaves):
             selection = selectiontools.ContiguousSelection(leaf_pair)
             selection._attach_tie_spanner_to_leaf_pair()
     # return result
     return result
def list_numbered_inversion_equivalent_interval_classes_pairwise(pitch_carriers, wrap=False):
    r'''List numbered inversion-equivalent interval-classes pairwise between
    `pitch_carriers`:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8 g'8 a'8 b'8 c''8")

    ..  doctest::

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

    ::

        >>> result = pitchtools.list_numbered_inversion_equivalent_interval_classes_pairwise(
        ... staff, wrap=False)

    ::

        >>> for x in result: x
        ...
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)

    ::

        >>> result = pitchtools.list_numbered_inversion_equivalent_interval_classes_pairwise(
        ... staff, wrap=True)

    ::

        >>> for x in result: x
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(0)

    ::

        >>> notes = staff.select_leaves()
        >>> notes = list(reversed(notes))

    ::

        >>> result = pitchtools.list_numbered_inversion_equivalent_interval_classes_pairwise(
        ... notes, wrap=False)

    ::

        >>> for x in result: x
        ...
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)

    ::

        >>> result = pitchtools.list_numbered_inversion_equivalent_interval_classes_pairwise(
        ... notes, wrap=True)

    ::

        >>> for x in result: x
        ...
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(1)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(2)
        NumberedInversionEquivalentIntervalClass(0)

    When ``wrap=False`` do not return ``pitch_carriers[-1] - pitch_carriers[0]`` as last in series.

    When ``wrap=True`` do return ``pitch_carriers[-1] - pitch_carriers[0]`` as last in series.

    Returns list.
    '''
    from abjad.tools import pitchtools

    result = []

    if len(pitch_carriers) == 0:
        return result
    elif len(pitch_carriers) == 1:
        if pitchtools.Pitch.is_pitch_carrier(pitch_carriers[0]):
            return result
        else:
            raise TypeError('must be Abjad pitch, note, note head or chord.')

    if wrap:
        pairs = sequencetools.iterate_sequence_pairwise_wrapped(pitch_carriers)
    else:
        pairs = sequencetools.iterate_sequence_pairwise_strict(pitch_carriers)

    for first_carrier, second_carrier in pairs:
        first_pitch = pitchtools.get_named_pitch_from_pitch_carrier(first_carrier)
        second_pitch = pitchtools.get_named_pitch_from_pitch_carrier(second_carrier)
        mdi = second_pitch - first_pitch
        iecic = pitchtools.NumberedInversionEquivalentIntervalClass(mdi)
        result.append(iecic)

    return result