def __copy__(self, *arguments): """ Shallow copies component. Copies indicators. Does not copy spanners. Does not copy children. Returns new component. """ new_component = type(self)(*self.__getnewargs__()) if getattr(self, "_overrides", None) is not None: manager = copy.copy(override(self)) new_component._overrides = manager if getattr(self, "_lilypond_setting_name_manager", None) is not None: manager = copy.copy(setting(self)) new_component._lilypond_setting_name_manager = manager for wrapper in inspect(self).annotation_wrappers(): new_wrapper = copy.copy(wrapper) attach(new_wrapper, new_component) for wrapper in inspect(self).wrappers(): new_wrapper = copy.copy(wrapper) attach(new_wrapper, new_component) return new_component
def _add_beam_counts(self, leaf, bundle): if (not isinstance(leaf, Leaf) or not self._is_beamable(leaf)): left, right = None, None elif self._is_exterior_leaf(leaf): left, right = self._get_left_right_for_exterior_leaf(leaf) elif self._is_just_left_of_gap(leaf): left = leaf.written_duration.flag_count next_leaf = inspect(leaf).leaf(1) if self._is_beamable( next_leaf, beam_rests=self.beam_rests, ): right = self.span_beam_count else: right = 0 elif self._is_just_right_of_gap(leaf): previous_leaf = inspect(leaf).leaf(-1) if self._is_beamable( previous_leaf, beam_rests=self.beam_rests, ): left = self.span_beam_count else: left = 0 right = leaf.written_duration.flag_count else: assert self._is_interior_leaf(leaf) left, right = self._get_left_right_for_interior_leaf(leaf) if left is not None: string = rf'\set stemLeftBeamCount = {left}' bundle.before.commands.append(string) if right is not None: string = rf'\set stemRightBeamCount = {right}' bundle.before.commands.append(string)
def _format_leaf_nucleus(self): indent = LilyPondFormatManager.indent result = [] note_heads = self.note_heads if any('\n' in format(x) for x in note_heads): for note_head in note_heads: current_format = format(note_head) format_list = current_format.split('\n') format_list = [indent + x for x in format_list] result.extend(format_list) result.insert(0, '<') result.append('>') result = '\n'.join(result) result += str(self._get_formatted_duration()) elif inspect(self).has_indicator(Tremolo): reattack_duration = self._get_tremolo_reattack_duration() duration_string = reattack_duration.lilypond_duration_string durated_pitches = [] for note_head in note_heads: durated_pitch = format(note_head) + duration_string durated_pitches.append(durated_pitch) tremolo = inspect(self).indicator(Tremolo) if tremolo.is_slurred: durated_pitches[0] = durated_pitches[0] + r' \(' durated_pitches[-1] = durated_pitches[-1] + r' \)' result = ' '.join(durated_pitches) else: result.extend([format(_) for _ in note_heads]) result = '<%s>%s' % ( ' '.join(result), self._get_formatted_duration(), ) # single string, but wrapped in list bc contribution return ['nucleus', [result]]
def _format_leaf_nucleus(self): indent = LilyPondFormatManager.indent result = [] note_heads = self.note_heads if any("\n" in format(x) for x in note_heads): for note_head in note_heads: current_format = format(note_head) format_list = current_format.split("\n") format_list = [indent + x for x in format_list] result.extend(format_list) result.insert(0, "<") result.append(">") result = "\n".join(result) result += str(self._get_formatted_duration()) elif inspect(self).has_indicator(Tremolo): reattack_duration = self._get_tremolo_reattack_duration() duration_string = reattack_duration.lilypond_duration_string durated_pitches = [] for note_head in note_heads: durated_pitch = format(note_head) + duration_string durated_pitches.append(durated_pitch) tremolo = inspect(self).indicator(Tremolo) if tremolo.is_slurred: durated_pitches[0] = durated_pitches[0] + r" \(" durated_pitches[-1] = durated_pitches[-1] + r" \)" result = " ".join(durated_pitches) else: result.extend([format(_) for _ in note_heads]) result = "<%s>%s" % ( " ".join(result), self._get_formatted_duration(), ) # single string, but wrapped in list bc contribution return ["nucleus", [result]]
def _get_persistent_wrappers(self, *, omit_annotation=None): self._update_now(indicators=True) wrappers = {} for wrapper in self._dependent_wrappers: if wrapper.annotation: continue indicator = wrapper.indicator if not getattr(indicator, "persistent", False): continue assert isinstance(indicator.persistent, bool) is_phantom = False if omit_annotation is not None: parentage = inspect(wrapper.component).parentage() for component in parentage: if inspect(component).annotation(omit_annotation) is True: is_phantom = True continue if is_phantom: continue if hasattr(indicator, "parameter"): key = indicator.parameter elif isinstance(indicator, Instrument): key = "Instrument" else: key = str(type(indicator)) if (key not in wrappers or wrappers[key].start_offset <= wrapper.start_offset): wrappers[key] = wrapper return wrappers
def _get_persistent_wrappers(self, *, omit_annotation=None): self._update_now(indicators=True) wrappers = {} for wrapper in self._dependent_wrappers: if wrapper.annotation: continue indicator = wrapper.indicator if not getattr(indicator, "persistent", False): continue assert isinstance(indicator.persistent, bool) is_phantom = False if omit_annotation is not None: parentage = inspect(wrapper.component).parentage() for component in parentage: if inspect(component).annotation(omit_annotation) is True: is_phantom = True continue if is_phantom: continue if hasattr(indicator, "parameter"): key = indicator.parameter elif isinstance(indicator, Instrument): key = "Instrument" else: key = str(type(indicator)) if ( key not in wrappers or wrappers[key].start_offset <= wrapper.start_offset ): wrappers[key] = wrapper return wrappers
def _get_persistent_wrappers(*, dependent_wrappers=None, omit_with_indicator=None): wrappers = {} for wrapper in dependent_wrappers: if wrapper.annotation: continue indicator = wrapper.indicator if not getattr(indicator, "persistent", False): continue assert isinstance(indicator.persistent, bool) should_omit = False if omit_with_indicator is not None: parentage = inspect(wrapper.component).parentage() for component in parentage: if inspect(component).has_indicator(omit_with_indicator): should_omit = True continue if should_omit: continue if hasattr(indicator, "parameter"): key = indicator.parameter elif isinstance(indicator, Instrument): key = "Instrument" else: key = str(type(indicator)) if (key not in wrappers or wrappers[key].start_offset <= wrapper.start_offset): wrappers[key] = wrapper return wrappers
def _get_measure_start_offsets(self, component): wrappers = [] prototype = TimeSignature root = inspect(component).parentage().root for component_ in self._iterate_entire_score(root): wrappers_ = inspect(component_).wrappers(prototype) wrappers.extend(wrappers_) pairs = [] for wrapper in wrappers: component = wrapper.component start_offset = inspect(component).timespan().start_offset time_signature = wrapper.indicator pair = start_offset, time_signature pairs.append(pair) offset_zero = Offset(0) default_time_signature = TimeSignature((4, 4)) default_pair = (offset_zero, default_time_signature) if pairs and not pairs[0] == offset_zero: pairs.insert(0, default_pair) elif not pairs: pairs = [default_pair] pairs.sort(key=lambda x: x[0]) score_stop_offset = inspect(root).timespan().stop_offset dummy_last_pair = (score_stop_offset, None) pairs.append(dummy_last_pair) measure_start_offsets = [] for current_pair, next_pair in Sequence(pairs).nwise(): current_start_offset, current_time_signature = current_pair next_start_offset, next_time_signature = next_pair measure_start_offset = current_start_offset while measure_start_offset < next_start_offset: measure_start_offsets.append(measure_start_offset) measure_start_offset += current_time_signature.duration return measure_start_offsets
def __copy__(self, *arguments): """ Shallow copies component. Copies indicators. Does not copy spanners. Does not copy children. Returns new component. """ new_component = type(self)(*self.__getnewargs__()) if getattr(self, "_overrides", None) is not None: manager = copy.copy(override(self)) new_component._overrides = manager if getattr(self, "_lilypond_setting_name_manager", None) is not None: manager = copy.copy(setting(self)) new_component._lilypond_setting_name_manager = manager for wrapper in inspect(self).annotation_wrappers(): new_wrapper = copy.copy(wrapper) attach(new_wrapper, new_component) for wrapper in inspect(self).wrappers(): new_wrapper = copy.copy(wrapper) attach(new_wrapper, new_component) return new_component
def _add_container_identifiers(self): if self.environment == "docs" and not getattr( self, "test_container_identifiers", False ): return segment_name = self.segment_name or "" segment_name = String(segment_name).to_segment_lilypond_identifier() contexts = [] try: context = self.score["Global_Skips"] contexts.append(context) except ValueError: pass try: context = self.score["Global_Rests"] contexts.append(context) except ValueError: pass for voice in iterate(self.score).components(Voice): if inspect(voice).annotation("INTERMITTENT") is True: continue contexts.append(voice) container_to_part_assignment = OrderedDict() for context in contexts: if segment_name: context_identifier = f"{segment_name}_{context.name}" else: context_identifier = context.name context.identifier = f"%*% {context_identifier}" part_container_count = 0 for container in iterate(context).components(Container): if not container.identifier: continue if container.identifier.startswith("%*% Part"): part_container_count += 1 globals_ = globals() part = container.identifier.strip("%*% ") part = eval(part, globals_) suffix = String().base_26(part_container_count).lower() container_identifier = f"{context_identifier}_{suffix}" container_identifier = String(container_identifier) assert container_identifier.is_lilypond_identifier() assert ( container_identifier not in container_to_part_assignment ) timespan = inspect(container).timespan() pair = (part, timespan) container_to_part_assignment[container_identifier] = pair container.identifier = f"%*% {container_identifier}" for staff in iterate(self.score).components(Staff): if segment_name: context_identifier = f"{segment_name}_{staff.name}" else: context_identifier = staff.name staff.identifier = f"%*% {context_identifier}" self._container_to_part_assignment = container_to_part_assignment
def _add_container_identifiers(self): if (self.environment == 'docs' and not getattr(self, 'test_container_identifiers', False)): return segment_name = self.segment_name or '' segment_name = String(segment_name).to_segment_lilypond_identifier() contexts = [] try: context = self.score['Global_Skips'] contexts.append(context) except ValueError: pass try: context = self.score['Global_Rests'] contexts.append(context) except ValueError: pass for voice in iterate(self.score).components(Voice): if inspect(voice).annotation('INTERMITTENT') is True: continue contexts.append(voice) container_to_part_assignment = OrderedDict() for context in contexts: if segment_name: context_identifier = f'{segment_name}_{context.name}' else: context_identifier = context.name context.identifier = f'%*% {context_identifier}' part_container_count = 0 for container in iterate(context).components(Container): if not container.identifier: continue if container.identifier.startswith('%*% Part'): part_container_count += 1 globals_ = globals() part = container.identifier.strip('%*% ') part = eval(part, globals_) suffix = String().base_26(part_container_count).lower() container_identifier = f'{context_identifier}_{suffix}' container_identifier = String(container_identifier) assert container_identifier.is_lilypond_identifier() assert container_identifier not in \ container_to_part_assignment timespan = inspect(container).timespan() pair = (part, timespan) container_to_part_assignment[container_identifier] = pair container.identifier = f'%*% {container_identifier}' for staff in iterate(self.score).components(Staff): if segment_name: context_identifier = f'{segment_name}_{staff.name}' else: context_identifier = staff.name staff.identifier = f'%*% {context_identifier}' self._container_to_part_assignment = container_to_part_assignment
def leaked_start_offset(self): r""" Gets start offset and checks to see whether indicator leaks to the right. This is either the wrapper's synthetic offset (if set); or the START offset of the wrapper's component (if indicator DOES NOT leak); or else the STOP offset of the wrapper's component (if indicator DOES leak). .. container:: example Start- and stop-text-spans attach to the same leaf. But stop-text-span leaks to the right: >>> voice = abjad.Voice("c'2 d'2") >>> start_text_span = abjad.StartTextSpan() >>> abjad.attach(start_text_span, voice[0]) >>> stop_text_span = abjad.StopTextSpan(leak=True) >>> abjad.attach(stop_text_span, voice[0]) >>> abjad.show(voice) # doctest: +SKIP >>> abjad.f(voice) \new Voice { c'2 \startTextSpan <> \stopTextSpan d'2 } Start offset and leaked start offset are the same for start-text-span: >>> wrapper = abjad.inspect(voice[0]).wrapper(abjad.StartTextSpan) >>> wrapper.start_offset, wrapper.leaked_start_offset (Offset((0, 1)), Offset((0, 1))) Start offset and leaked start offset differ for stop-text-span: >>> wrapper = abjad.inspect(voice[0]).wrapper(abjad.StopTextSpan) >>> wrapper.start_offset, wrapper.leaked_start_offset (Offset((0, 1)), Offset((1, 2))) Returns offset. """ from abjad.top.inspect import inspect if self._synthetic_offset is not None: return self._synthetic_offset if not getattr(self.indicator, "leak", False): return inspect(self._component).timespan().start_offset else: return inspect(self._component).timespan().stop_offset
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 exceptions.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], 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) if not inspect(self).has_spanner(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 inspect(self).has_spanner(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 _split_simultaneous_by_duration( self, duration, tie_split_notes=True, repeat_ties=False ): assert self.is_simultaneous left_components, right_components = [], [] for component in self[:]: halves = component._split_by_duration( duration=duration, tie_split_notes=tie_split_notes, repeat_ties=repeat_ties, ) left_components_, right_components_ = halves left_components.extend(left_components_) right_components.extend(right_components_) left_components = select(left_components) right_components = select(right_components) left_container = self.__copy__() right_container = self.__copy__() left_container.extend(left_components) right_container.extend(right_components) if inspect(self).parentage().parent is not None: containers = select([left_container, right_container]) mutate(self).replace(containers) # return list-wrapped halves of container return [left_container], [right_container]
def _update_now( self, component, offsets=False, offsets_in_seconds=False, indicators=False, ): assert offsets or offsets_in_seconds or indicators if component._is_forbidden_to_update: return parentage = inspect(component).parentage() for parent in parentage: if parent._is_forbidden_to_update: return ( offsets_are_current, indicators_are_current, offsets_in_seconds_are_current, ) = self._get_score_tree_state_flags(parentage) root = parentage.root if offsets and not offsets_are_current: self._update_all_offsets(root) if offsets_in_seconds and not offsets_in_seconds_are_current: self._update_all_offsets_in_seconds(root) if indicators and not indicators_are_current: self._update_all_indicators(root)
def _update_later(self, offsets=False, offsets_in_seconds=False): assert offsets or offsets_in_seconds for component in inspect(self).parentage(): if offsets: component._offsets_are_current = False elif offsets_in_seconds: component._offsets_in_seconds_are_current = False
def _all_are_orphan_components(argument): for component in argument: if not isinstance(component, Component): return False if not inspect(component).parentage().orphan: return False return True
def _split_simultaneous_by_duration( self, duration, tie_split_notes=True, repeat_ties=False, ): assert self.is_simultaneous left_components, right_components = [], [] for component in self[:]: halves = component._split_by_duration( duration=duration, tie_split_notes=tie_split_notes, repeat_ties=repeat_ties, ) left_components_, right_components_ = halves left_components.extend(left_components_) right_components.extend(right_components_) left_components = select(left_components) right_components = select(right_components) left_container = self.__copy__() right_container = self.__copy__() left_container.extend(left_components) right_container.extend(right_components) if inspect(self).parentage().parent is not None: containers = select([left_container, right_container]) mutate(self).replace(containers) # return list-wrapped halves of container return [left_container], [right_container]
def _parse_string(self, string): from abjad.parser.ReducedLyParser import ReducedLyParser from abjad.lilypondfile.LilyPondFile import LilyPondFile user_input = string.strip() if user_input.startswith('abj:'): parser = ReducedLyParser() parsed = parser(user_input[4:]) if parser._toplevel_component_count == 1: parent = inspect(parsed).parentage().parent if parent is None: parsed = Container([parsed]) else: parsed = parent elif user_input.startswith('rtm:'): parsed = rhythmtrees.parse_rtm_syntax(user_input[4:]) else: if ( not user_input.startswith('<<') or not user_input.endswith('>>') ): user_input = f'{{ {user_input} }}' parsed = parse(user_input) if isinstance(parsed, LilyPondFile): parsed = Container(parsed.items[:]) assert isinstance(parsed, Container) return parsed
def _update_later(self, offsets=False, offsets_in_seconds=False): assert offsets or offsets_in_seconds for component in inspect(self).parentage(): if offsets: component._offsets_are_current = False elif offsets_in_seconds: component._offsets_in_seconds_are_current = False
def _all_are_orphan_components(argument): for component in argument: if not isinstance(component, Component): return False if not inspect(component).parentage().orphan: return False return True
def _parse_string(self, string): from abjad.parser.ReducedLyParser import ReducedLyParser from abjad.lilypondfile.LilyPondFile import LilyPondFile user_input = string.strip() if user_input.startswith("abj:"): parser = ReducedLyParser() parsed = parser(user_input[4:]) if parser._toplevel_component_count == 1: parent = inspect(parsed).parentage().parent if parent is None: parsed = Container([parsed]) else: parsed = parent elif user_input.startswith("rtm:"): parsed = rhythmtrees.parse_rtm_syntax(user_input[4:]) else: if not user_input.startswith("<<") or not user_input.endswith( ">>" ): user_input = f"{{ {user_input} }}" parsed = parse(user_input) if isinstance(parsed, LilyPondFile): parsed = Container(parsed.items[:]) assert isinstance(parsed, Container) return parsed
def _next_leaf_is_bowed(self, leaf): if leaf is self[-1]: return False prototype = ( MultimeasureRest, Rest, Skip, ) next_leaf = inspect(leaf).leaf(1) if next_leaf is None or isinstance(next_leaf, prototype): return False next_contact_point = inspect(next_leaf).indicator(BowContactPoint) if next_contact_point is None: return False elif next_contact_point.contact_point is None: return False return True
def _sibling(self, n): assert n in (-1, 0, 1), repr(n) if n == 0: return self for parent in inspect(self).parentage(): sibling = parent._get_sibling(mathtools.sign(n)) if sibling is not None: return sibling
def _attachment_test(self, component): if self._ignore_attachment_test: return True if not isinstance(component, (Chord, Note)): return False if inspect(component).has_spanner(Tie): return False return True
def _get_effective_staff(self): from .Staff import Staff staff_change = self._get_effective(StaffChange) if staff_change is not None: effective_staff = staff_change.staff else: effective_staff = inspect(self).parentage().get(Staff) return effective_staff
def _update_measure_numbers(self, component): measure_start_offsets = self._get_measure_start_offsets(component) root = inspect(component).parentage().root for component in self._iterate_entire_score(root): measure_number = self._to_measure_number( component, measure_start_offsets ) component._measure_number = measure_number
def _get_duration(self, in_seconds=False): if in_seconds: return self._get_duration_in_seconds() elif self._parent is None: return self._get_preprolated_duration() else: parentage = inspect(self._parent).parentage() return parentage.prolation * self._get_preprolated_duration()
def _add_stemlet_length(self, leaf, bundle): if self.stemlet_length is None: return if leaf is self[0]: parentage = inspect(leaf).parentage() staff = parentage.get_first(Staff) lilypond_type = staff.lilypond_type string = r'\override {}.Stem.stemlet-length = {}' string = string.format(lilypond_type, self.stemlet_length) bundle.before.commands.append(string) if leaf is self[-1]: parentage = inspect(leaf).parentage() staff = parentage.get_first(Staff) lilypond_type = staff.lilypond_type string = r'\revert {}.Stem.stemlet-length' string = string.format(lilypond_type, self.stemlet_length) bundle.before.commands.append(string)
def _get_duration(self, in_seconds=False): if in_seconds: return self._get_duration_in_seconds() elif self._parent is None: return self._get_preprolated_duration() else: parentage = inspect(self._parent).parentage() return parentage.prolation * self._get_preprolated_duration()
def _eject_contents(self): if inspect(self).parentage().parent is not None: message = "can not eject contents of in-score container." raise Exception(message) contents = self[:] for component in contents: component._set_parent(None) self._components[:] = [] return contents
def _iterate_topmost(self): for component in self: if isinstance(component, Leaf): logical_tie = inspect(component).logical_tie() if logical_tie.is_trivial or logical_tie[-1] is component: yield logical_tie else: assert isinstance(component, Container) yield component
def _get_tremolo_reattack_duration(self): tremolos = inspect(self).indicators(Tremolo) if not tremolos: return tremolo = tremolos[0] exponent = 2 + tremolo.beam_count denominator = 2 ** exponent reattack_duration = Duration(1, denominator) return reattack_duration
def _restore_named_children_to_parentage(self, name_dictionary): if self._parent is not None and name_dictionary: for parent in inspect(self).parentage()[1:]: named_children = parent._named_children for name in name_dictionary: if name in named_children: named_children[name].extend(name_dictionary[name]) else: named_children[name] = copy.copy(name_dictionary[name])
def _add_or_remove_notes_to_achieve_written_duration( self, new_written_duration): from abjad.spanners import tie as abjad_tie from .NoteMaker import NoteMaker from .Tuplet import Tuplet new_written_duration = Duration(new_written_duration) maker = NoteMaker() if new_written_duration.is_assignable: self[0].written_duration = new_written_duration for leaf in self[1:]: mutate(leaf).extract() detach(Tie, self[0]) detach(RepeatTie, self[0]) elif new_written_duration.has_power_of_two_denominator: durations = maker(0, [new_written_duration]) for leaf, token in zip(self, durations): leaf.written_duration = token.written_duration if len(self) == len(durations): pass elif len(durations) < len(self): for leaf in self[len(durations):]: mutate(leaf).extract() elif len(self) < len(durations): # detach(Tie, self[0]) detach(Tie, self[0]) detach(RepeatTie, self[0]) difference = len(durations) - len(self) extra_leaves = self[0] * difference for extra_leaf in extra_leaves: # detach(Tie, extra_leaf) detach(Tie, extra_leaf) detach(RepeatTie, extra_leaf) extra_tokens = durations[len(self):] for leaf, token in zip(extra_leaves, extra_tokens): leaf.written_duration = token.written_duration parent = inspect(self[-1]).parentage().parent index = parent.index(self[-1]) next_ = index + 1 parent[next_:next_] = extra_leaves leaves = self.leaves + extra_leaves # attach(Tie(), leaves) abjad_tie(leaves) else: components = maker(0, new_written_duration) assert isinstance(components[0], Tuplet) tuplet = components[0] logical_tie = tuplet[0]._get_logical_tie() duration = logical_tie._get_preprolated_duration() leaves_ = self._add_or_remove_notes_to_achieve_written_duration( duration) multiplier = tuplet.multiplier tuplet = Tuplet(multiplier, []) # mutate(self.leaves).wrap(tuplet) mutate(leaves_).wrap(tuplet) return self[0]._get_logical_tie()
def _get_effective_staff(self): from .Staff import Staff staff_change = self._get_effective(StaffChange) if staff_change is not None: effective_staff = staff_change.staff else: effective_staff = inspect(self).parentage().get(Staff) return effective_staff
def _remove_named_children_from_parentage(self, name_dictionary): if self._parent is not None and name_dictionary: for parent in inspect(self).parentage()[1:]: named_children = parent._named_children for name in name_dictionary: for component in name_dictionary[name]: named_children[name].remove(component) if not named_children[name]: del named_children[name]
def _fracture_right(self, i): self, left, right = Spanner._fracture_right(self, i) if self.durations: weights = [ inspect(left).duration(), inspect(right).duration(), ] assert sum(self.durations) == sum(weights) split_durations = sequence(self.durations) split_durations = split_durations.split( weights, cyclic=False, overhang=False, ) left_durations, right_durations = split_durations left._durations = left_durations right._durations = right_durations return self, left, right
def _iterate_topmost(self): for component in self: if isinstance(component, Leaf): logical_tie = inspect(component).logical_tie() if logical_tie.is_trivial or logical_tie[-1] is component: yield logical_tie else: assert isinstance(component, Container) yield component
def _stop_command_string(self): leaf = self[-1] if self._has_sounding_stop_dynamic(): string = self._get_directed_stop_dynamic() return string effective_dynamic = inspect(leaf).effective(Dynamic) if effective_dynamic is None or effective_dynamic.name == 'niente': string = self._stop_command return string if effective_dynamic not in inspect(leaf).wrappers(): found_match = False for indicator in inspect(leaf).indicators(Dynamic): if indicator == effective_dynamic: found_match = True if not found_match: string = self._stop_command return string return None
def _next_leaf_changes_current_pitch(leaf): next_leaf = inspect(leaf).leaf(n=1) if (isinstance(leaf, Note) and isinstance(next_leaf, Note) and leaf.written_pitch == next_leaf.written_pitch): return False elif (isinstance(leaf, Chord) and isinstance(next_leaf, Chord) and leaf.written_pitches == next_leaf.written_pitches): return False return True
def _get_tremolo_reattack_duration(self): tremolos = inspect(self).indicators(Tremolo) if not tremolos: return tremolo = tremolos[0] exponent = 2 + tremolo.beam_count denominator = 2**exponent reattack_duration = Duration(1, denominator) return reattack_duration
def _eject_contents(self): if inspect(self).parentage().parent is not None: message = 'can not eject contents of in-score container.' raise Exception(message) contents = self[:] for component in contents: component._set_parent(None) self._components[:] = [] return contents
def _previous_leaf_changes_current_pitch(leaf): previous_leaf = inspect(leaf).leaf(n=-1) if (isinstance(leaf, Note) and isinstance(previous_leaf, Note) and leaf.written_pitch == previous_leaf.written_pitch): return False elif (isinstance(leaf, Chord) and isinstance(previous_leaf, Chord) and leaf.written_pitches == previous_leaf.written_pitches): return False return True
def ratio(self) -> Ratio: """ Gets ratio of metric modulation. .. container:: example >>> metric_modulation = abjad.MetricModulation( ... left_rhythm=abjad.Tuplet((2, 3), [abjad.Note("c'4")]), ... right_rhythm=abjad.Note("c'4"), ... ) >>> metric_modulation.ratio Ratio((2, 3)) """ left_duration = inspect(self.left_rhythm).duration() right_duration = inspect(self.right_rhythm).duration() duration = left_duration / right_duration ratio = Ratio(duration.pair) return ratio
def start_components(self): """ Tuple of components in vertical moment starting with at vertical moment, ordered by score index. """ result = [] for component in self.components: if inspect(component).timespan().start_offset == self.offset: result.append(component) result = tuple(result) return result
def _format_repeat_tremolo_command(self): tremolo = inspect(self).indicator(Tremolo) reattack_duration = self._get_tremolo_reattack_duration() repeat_count = self.written_duration / reattack_duration / 2 if not mathtools.is_integer_equivalent(repeat_count): message = f"can not tremolo duration {self.written_duration}" message += f" with {tremolo.beam_count} beams." raise Exception(message) repeat_count = int(repeat_count) command = r"\repeat tremolo {}".format(repeat_count) return command
def _get_sounding_pitch(self): if "sounding pitch" in inspect(self).indicators(str): return self.written_pitch else: instrument = self._get_effective(instruments.Instrument) if instrument: sounding_pitch = instrument.middle_c_sounding_pitch else: sounding_pitch = NamedPitch("C4") interval = NamedPitch("C4") - sounding_pitch sounding_pitch = interval.transpose(self.written_pitch) return sounding_pitch
def _get_logical_tie(self): from .LogicalTie import LogicalTie leaves_before, leaves_after = [], [] current_leaf = self while True: previous_leaf = inspect(current_leaf).leaf(-1) if previous_leaf is None: break if inspect(current_leaf).has_indicator(RepeatTie) or inspect( previous_leaf ).has_indicator(TieIndicator): leaves_before.insert(0, previous_leaf) else: break current_leaf = previous_leaf current_leaf = self while True: next_leaf = inspect(current_leaf).leaf(1) if next_leaf is None: break if inspect(current_leaf).has_indicator(TieIndicator) or inspect( next_leaf ).has_indicator(RepeatTie): leaves_after.append(next_leaf) else: break current_leaf = next_leaf leaves = leaves_before + [self] + leaves_after return LogicalTie(items=leaves)
def _remove_from_parent(self): from .Context import Context self._update_later(offsets=True) for component in inspect(self).parentage()[1:]: if not isinstance(component, Context): continue for wrapper in component._dependent_wrappers[:]: if wrapper.component is self: component._dependent_wrappers.remove(wrapper) if self._parent is not None: self._parent._components.remove(self) self._parent = None
def start_offset(self): """ Gets start offset. This is either the wrapper's synthetic offset or the start offset of the wrapper's component. Returns offset. """ from abjad.top.inspect import inspect if self._synthetic_offset is not None: return self._synthetic_offset return inspect(self._component).timespan().start_offset
def _as_graphviz_node(self): score_index = inspect(self).parentage().score_index() score_index = "_".join(str(_) for _ in score_index) class_name = type(self).__name__ if score_index: name = f"{class_name}_{score_index}" else: name = class_name node = uqbar.graphs.Node( name=name, attributes={"margin": 0.05, "style": "rounded"} ) table = uqbar.graphs.Table(attributes={"border": 2, "cellpadding": 5}) node.append(table) return node
def _get_sounding_pitches(self): if "sounding pitch" in inspect(self).indicators(str): return self.written_pitches else: instrument = self._get_effective(instruments.Instrument) if instrument: sounding_pitch = instrument.middle_c_sounding_pitch else: sounding_pitch = abjad_pitch.NamedPitch("C4") interval = abjad_pitch.NamedPitch("C4") - sounding_pitch sounding_pitches = [ interval.transpose(pitch) for pitch in self.written_pitches ] return tuple(sounding_pitches)
def check_missing_parents( self, argument=None ) -> typing.Tuple[typing.List, int]: """ Checks missing parents. """ violators, total = [], set() components = iterate(argument).components() for i, component in enumerate(components): total.add(component) if 0 < i: parentage = inspect(component).parentage(grace_notes=True) if parentage.parent is None: violators.append(component) return violators, len(total)
def name(self, argument): assert isinstance(argument, (str, type(None))) old_name = self._name for parent in inspect(self).parentage()[1:]: named_children = parent._named_children if old_name is not None: named_children[old_name].remove(self) if not named_children[old_name]: del named_children[old_name] if argument is not None: if argument not in named_children: named_children[argument] = [self] else: named_children[argument].append(self) self._name = argument
def _format_before_slot(self, bundle): result = [] result.append(self._format_grace_body()) result.append(("comments", bundle.before.comments)) commands = bundle.before.commands if inspect(self).has_indicator(Tremolo): tremolo_command = self._format_repeat_tremolo_command() commands = list(commands) commands.append(tremolo_command) commands = tuple(commands) result.append(("commands", commands)) result.append(("indicators", bundle.before.indicators)) result.append(("grob overrides", bundle.grob_overrides)) result.append(("context settings", bundle.context_settings)) result.append(("spanners", bundle.before.spanners)) return result
def _should_force_repeat_tie_up(leaf): from abjad.core.Chord import Chord from abjad.core.Note import Note if not isinstance(leaf, (Note, Chord)): return False if leaf.written_duration < Duration(1): return False clef = inspect(leaf).effective(Clef, default=Clef("treble")) if isinstance(leaf, Note): written_pitches = [leaf.written_pitch] else: written_pitches = leaf.written_pitches for written_pitch in written_pitches: staff_position = written_pitch.to_staff_position(clef=clef) if staff_position.number == 0: return True return False
def _set_item(self, i, argument): from .GraceContainer import GraceContainer argument_indicators = [] for component in iterate(argument).components(): wrappers = inspect(component).wrappers() argument_indicators.extend(wrappers) if isinstance(i, int): argument = [argument] if i < 0: i = len(self) + i i = slice(i, i + 1) prototype = (Component, Selection) assert all(isinstance(_, prototype) for _ in argument) new_argument = [] for item in argument: if isinstance(item, Selection): new_argument.extend(item) else: new_argument.append(item) argument = new_argument assert all(isinstance(_, Component) for _ in argument) if any(isinstance(_, GraceContainer) for _ in argument): raise Exception("must attach grace container to note or chord.") if self._check_for_cycles(argument): raise exceptions.ParentageError("attempted to induce cycles.") if ( i.start == i.stop and i.start is not None and i.stop is not None and i.start <= -len(self) ): start, stop = 0, 0 else: start, stop, stride = i.indices(len(self)) old_components = self[start:stop] del self[start:stop] self._components.__setitem__(slice(start, start), argument) for component in argument: component._set_parent(self) for indicator in argument_indicators: if hasattr(indicator, "_update_effective_context"): indicator._update_effective_context()
def _split_by_duration( self, duration, tie_split_notes=True, repeat_ties=False ): if self.is_simultaneous: return self._split_simultaneous_by_duration( duration=duration, tie_split_notes=tie_split_notes, repeat_ties=repeat_ties, ) duration = Duration(duration) assert 0 <= duration, repr(duration) if duration == 0: return [], self # get split point score offset timespan = inspect(self).timespan() global_split_point = timespan.start_offset + duration # get any duration-crossing descendents cross_offset = timespan.start_offset + duration duration_crossing_descendants = [] for descendant in inspect(self).descendants(): timespan = inspect(descendant).timespan() start_offset = timespan.start_offset stop_offset = timespan.stop_offset if start_offset < cross_offset < stop_offset: duration_crossing_descendants.append(descendant) # 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, Leaf): assert isinstance(bottom, Leaf) did_split_leaf = True timespan = inspect(bottom).timespan() start_offset = timespan.start_offset split_point_in_bottom = global_split_point - start_offset new_leaves = bottom._split_by_durations( [split_point_in_bottom], tie_split_notes=tie_split_notes, repeat_ties=repeat_ties, ) for leaf in new_leaves: timespan = inspect(leaf).timespan() if timespan.stop_offset == global_split_point: leaf_left_of_split = leaf if timespan.start_offset == global_split_point: leaf_right_of_split = leaf 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).leaves(): timespan = inspect(leaf).timespan() if timespan.start_offset == global_split_point: leaf_right_of_split = leaf leaf_left_of_split = inspect(leaf).leaf(-1) break else: raise Exception("can not split empty container {bottom!r}.") assert leaf_left_of_split is not None assert leaf_right_of_split is not None # find component to right of split # that is also immediate child of last duration-crossing container for component in inspect(leaf_right_of_split).parentage(): parent = inspect(component).parentage().parent if parent is duration_crossing_containers[-1]: highest_level_component_right_of_split = component break else: raise ValueError("should not be able to get here.") # crawl back up through duration-crossing containers and split each previous = highest_level_component_right_of_split for container in reversed(duration_crossing_containers): assert isinstance(container, Container) index = container.index(previous) left, right = container._split_at_index(index) previous = right # 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, Note): if ( inspect(leaf_left_of_split).parentage().root is inspect(leaf_right_of_split).parentage().root ): leaves_around_split = ( leaf_left_of_split, leaf_right_of_split, ) selection = select(leaves_around_split) selection._attach_tie_to_leaves(repeat_ties=repeat_ties) # return list-wrapped halves of container return [left], [right]