def _set_duration(self, new_duration, repeat_ties=False): import abjad new_duration = Duration(new_duration) # change LilyPond multiplier if leaf already has LilyPond multiplier if self._get_indicators(Multiplier): detach(Multiplier, self) multiplier = new_duration.__div__(self.written_duration) attach(multiplier, self) return select(self) # change written duration if new duration is assignable try: self.written_duration = new_duration return select(self) except AssignabilityError: pass # make new notes or tuplets if new duration is nonassignable maker = abjad.NoteMaker(repeat_ties=repeat_ties, ) components = maker(0, new_duration) if isinstance(components[0], abjad.Leaf): tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for leaf, component in zip(all_leaves, components): leaf.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) parentage = abjad.inspect(self).get_parentage() if not abjad.inspect(parentage).get_spanners(abjad.Tie): tie = abjad.Tie() if tie._attachment_test(self): tie = abjad.Tie(repeat=repeat_ties) attach(tie, all_leaves) return select(all_leaves) else: assert isinstance(components[0], abjad.Tuplet) tuplet = components[0] components = tuplet[:] tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for leaf, component in zip(all_leaves, components): leaf.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) if not self._get_spanners(abjad.Tie): tie = abjad.Tie() if tie._attachment_test(self): tie = abjad.Tie(repeat=repeat_ties) attach(tie, all_leaves) multiplier = tuplet.multiplier tuplet = abjad.Tuplet(multiplier, []) abjad.mutate(all_leaves).wrap(tuplet) return select(tuplet)
def _at_least_two_leaves(self, argument): leaves = select(argument).leaves() if 1 < len(leaves): return True return [ 'Requires at least two leaves.', f'Not just {leaves[0]!r}.', ]
def leaves(self) -> Selection: r'''Gets leaves in spanner. ''' for leaf in self._leaves: if not isinstance(leaf, Leaf): message = f'spanners attach only to leaves (not {leaf!s}).' raise Exception(message) return select(self._leaves)
def __getitem__(self, argument): r'''Gets item or slice identified by `argument`. Returns leaf. ''' if isinstance(argument, slice): leaves = self.leaves.__getitem__(argument) return select(leaves) return self.leaves.__getitem__(argument)
def previous(component): new_component = component._get_nth_component_in_time_order_from(-1) if new_component is None: return candidates = new_component._get_descendants_stopping_with() candidates = [x for x in candidates if isinstance(x, abjad.Leaf)] for candidate in candidates: selection = select([component, candidate]) if selection.are_logical_voice(): return candidate
def _extend(self, leaves): leaf_input = list(self[-1:]) leaf_input.extend(leaves) leaf_input = select(leaf_input) if self._contiguity_constraint == 'logical voice': if not leaf_input.are_contiguous_logical_voice(): message = f'{self!r} leaves must be contiguous:\n' message += f' {leaf_input}' raise Exception(message) for leaf in leaves: self._append(leaf)
def _initialize_rhythm(self, rhythm): import abjad if isinstance(rhythm, abjad.Component): selection = select([rhythm]) elif isinstance(rhythm, abjad.Selection): selection = rhythm else: message = 'rhythm must be duration, component or selection: {!r}.' message = message.format(rhythm) raise TypeError(message) assert isinstance(selection, abjad.Selection) return selection
def _append(self, leaf): if self._ignore_attachment_test: pass elif not self._attachment_test(leaf): message = f'can not attach {self!r} to {leaf!r}.' raise Exception(message) if self._contiguity_constraint == 'logical voice': leaves = self[-1:] + [leaf] leaves = select(leaves) if not leaves.are_contiguous_logical_voice(): raise Exception(type(self), leaves) leaf._append_spanner(self) self._leaves.append(leaf)
def attach_defaults(self, argument) -> typing.List: r'''Attaches defaults to all staff and staff group contexts in ``argument`` when ``argument`` is a score. Attaches defaults to ``argument`` (without iterating ``argument``) when ``argument`` is a staff or staff group. Returns list of one wrapper for every indicator attached. ''' assert isinstance(argument, (Score, Staff, StaffGroup)), repr(argument) wrappers: typing.List[Wrapper] = [] tag = Tags().REMOVE_ALL_EMPTY_STAVES empty_prototype = (MultimeasureRest, Skip) prototype = (Staff, StaffGroup) if isinstance(argument, Score): staff__groups = select(argument).components(prototype) staves = select(argument).components(Staff) elif isinstance(argument, Staff): staff__groups = [argument] staves = [argument] else: assert isinstance(argument, StaffGroup), repr(argument) staff__groups = [argument] staves = [] for staff__group in staff__groups: leaf = None voices = select(staff__group).components(Voice) # find first leaf in first nonempty voice for voice in voices: leaves = select(voice).leaves() if not all(isinstance(_, empty_prototype) for _ in leaves): leaf = inspect(voice).get_leaf(0) # otherwise, find first leaf in voice in non-removable staff if leaf is None: for voice in voices: voice_might_vanish = False for component in inspect(voice).get_parentage(): if inspect(component).get_annotation(tag) is True: voice_might_vanish = True if not voice_might_vanish: leaf = inspect(voice).get_leaf(0) if leaf is not None: break # otherwise, as last resort find first leaf in first voice if leaf is None: leaf = inspect(voices[0]).get_leaf(0) if leaf is None: continue instrument = inspect(leaf).get_indicator(Instrument) if instrument is None: string = 'default_instrument' instrument = inspect(staff__group).get_annotation(string) if instrument is not None: wrapper = attach(instrument, leaf, tag='ST1', wrapper=True) wrappers.append(wrapper) margin_markup = inspect(leaf).get_indicator(MarginMarkup) if margin_markup is None: string = 'default_margin_markup' margin_markup = inspect(staff__group).get_annotation(string) if margin_markup is not None: wrapper = attach( margin_markup, leaf, tag=Tag('-PARTS').prepend('ST2'), wrapper=True, ) wrappers.append(wrapper) for staff in staves: leaf = inspect(staff).get_leaf(0) clef = inspect(leaf).get_indicator(Clef) if clef is not None: continue clef = inspect(staff).get_annotation('default_clef') if clef is not None: wrapper = attach(clef, leaf, tag='ST3', wrapper=True) wrappers.append(wrapper) return wrappers
def _split_by_durations( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, repeat_ties=False, ): import abjad durations = [Duration(_) for _ in durations] durations = abjad.sequence(durations) leaf_duration = abjad.inspect(self).get_duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = abjad.sequence(durations) durations = durations.truncate(weight=leaf_duration) result_selections = [] # detach grace containers grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = abjad.inspect(self).get_parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties, ) result_selections.append(selection) result_components = abjad.sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves() assert all(isinstance(_, abjad.Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() if abjad.inspect(self).has_spanner(abjad.Tie): for leaf in result_leaves: detach(abjad.Tie, leaf) # strip result leaves of indicators (other than multipliers) for leaf in result_leaves: multiplier = abjad.inspect(leaf).get_indicator(Multiplier) detach(object, leaf) if multiplier is not None: attach(multiplier, leaf) # replace leaf with flattened result selection = select(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), result_components) else: selection._give_dominant_spanners(result_components) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_selection = result_selections[0] for spanner in abjad.inspect(first_selection[-1]).get_spanners(): index = spanner._index(first_selection[-1]) spanner._fracture(index, direction=abjad.Right) last_selection = result_selections[-1] for spanner in abjad.inspect(last_selection[0]).get_spanners(): index = spanner._index(last_selection[0]) spanner._fracture(index, direction=abjad.Left) for middle_selection in result_selections[1:-1]: spanners = abjad.inspect(middle_selection[0]).get_spanners() for spanner in spanners: index = spanner._index(middle_selection[0]) spanner._fracture(index, direction=abjad.Left) spanners = abjad.inspect(middle_selection[-1]).get_spanners() for spanner in spanners: index = spanner._index(middle_selection[-1]) spanner._fracture(index, direction=abjad.Right) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in abjad.inspect(self).get_indicators(): if isinstance(indicator, Multiplier): continue detach(indicator, self) direction = getattr(indicator, '_time_orientation', abjad.Left) if direction == abjad.Left: attach(indicator, first_result_leaf) elif direction == abjad.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, abjad.GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = abjad.AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], abjad.Tuplet): abjad.mutate(result_components).fuse() # tie split notes if isinstance(self, (abjad.Note, abjad.Chord)) and tie_split_notes: result_leaves._attach_tie_spanner_to_leaves( repeat_ties=repeat_ties, ) assert isinstance(result_selections, list), repr(result_selections) assert all(isinstance(_, abjad.Selection) for _ in result_selections) return result_selections
def _extend_left(self, leaves): leaf_input = leaves + list(self[:1]) leaf_input = select(leaf_input) assert leaf_input.are_contiguous_logical_voice() for leaf in reversed(leaves): self._append_left(leaf)
def _append_left(self, leaf): leaves = [leaf] + self[:1] leaves = select(leaves) assert leaves.are_contiguous_logical_voice() leaf._append_spanner(self) self._leaves.insert(0, leaf)