def __sub__(self, timespan): r'''Subtract `timespan` from start-positioned payload expression. Operates in place and returns timespan inventory. ''' if timespan.delays_timespan(self): split_offset = durationtools.Offset(timespan.stop_offset) duration_to_trim = split_offset - self.start_offset result = self._split_payload_at_offsets([duration_to_trim]) trimmed_payload = result[-1] self._payload = trimmed_payload self._start_offset = split_offset result = timespantools.TimespanInventory([self]) elif timespan.curtails_timespan(self): split_offset = durationtools.Offset(timespan.start_offset) duration_to_trim = self.stop_offset - split_offset if hasattr(self.payload, 'duration'): payload_duration = self.payload.duration else: payload_duration = self.payload._get_duration() duration_to_keep = payload_duration - duration_to_trim result = self._split_payload_at_offsets([duration_to_keep]) trimmed_payload = result[0] self._payload = trimmed_payload result = timespantools.TimespanInventory([self]) elif timespan.trisects_timespan(self): split_offsets = [] split_offsets.append(timespan.start_offset - self.start_offset) split_offsets.append(timespan.duration) result = self._split_payload_at_offsets(split_offsets) left_payload = result[0] right_payload = result[-1] left_timespan = timespantools.Timespan(self.start_offset) left_payload_expression = type(self)( payload=[], start_offset=left_timespan.start_offset, voice_name=self.voice_name, ) left_payload_expression._payload = left_payload right_timespan = timespantools.Timespan(timespan.stop_offset) right_payload_expression = type(self)( payload=[], start_offset=right_timespan.start_offset, voice_name=self.voice_name, ) right_payload_expression._payload = right_payload payload_expressions = \ [left_payload_expression, right_payload_expression] result = timespantools.TimespanInventory(payload_expressions) else: result = timespantools.TimespanInventory([self]) return result
def supply_missing_set_expressions(self, attribute, score_specification, voice_name): r'''Operates in place and returns inventory. ''' assert self.is_sorted if not self and not score_specification.time_signatures: return self elif not self and score_specification.time_signatures: timespan = score_specification.timespan set_expression = \ score_specification.make_default_timespan_delimited_single_context_set_expression( attribute, timespan, voice_name) self[:] = [set_expression] return self timespans = timespantools.TimespanInventory( [expr.target_timespan for expr in self]) timespans.append(score_specification.timespan) missing_region_timespans = timespans.compute_logical_xor() for missing_region_timespan in missing_region_timespans: missing_set_expression = \ score_specification.make_default_timespan_delimited_single_context_set_expression( attribute, missing_region_timespan, voice_name) self.append(missing_set_expression) self.sort() return self
def __or__(self, expr): r'''Logical OR of two payload expressions. Payload expression must be able to fuse. Returns timespan inventory. ''' assert self._can_fuse(expr) if isinstance(self.payload, scoretools.Container): selection = select(self.payload[0], contiguous=True) left = mutate(selection).copy()[0] selection = select(expr.payload[0], contiguous=True) right = mutate(selection).copy()[0] payload = scoretools.Container([left, right]) for component in payload[:]: component._extract() payload = scoretools.Container([payload]) else: payload = self.payload + expr.payload result = type(self)( [], start_offset=self.timespan.start_offset, voice_name=self.voice_name, ) result._payload = payload return timespantools.TimespanInventory([result])
def __init__(self): from experimental.tools import musicexpressiontools self._leaf_start_offsets = [] self._leaf_stop_offsets = [] self._leaves = [] self._payload_expressions_by_attribute = \ musicexpressiontools.AttributeDictionary() for attribute in self._payload_expressions_by_attribute: self._payload_expressions_by_attribute[attribute] = \ timespantools.TimespanInventory() self._voice_division_list = None
def __and__(self, timespan): r'''Keep intersection of start-positioned payload expression and `timespan`. Operates in place and returns timespan inventory. ''' if timespan.contains_timespan_improperly(self): result = timespantools.TimespanInventory([self]) elif timespan.delays_timespan(self): split_offset = durationtools.Offset(timespan.stop_offset) duration_to_keep = split_offset - self.start_offset result = self._split_payload_at_offsets([duration_to_keep]) trimmed_payload = result[0] self._payload = trimmed_payload result = timespantools.TimespanInventory([self]) elif timespan.curtails_timespan(self): split_offset = durationtools.Offset(timespan.start_offset) duration_to_trim = split_offset - self.start_offset result = self._split_payload_at_offsets([duration_to_trim]) trimmed_payload = result[-1] self._payload = trimmed_payload self._start_offset = split_offset result = timespantools.TimespanInventory([self]) elif timespan.trisects_timespan(self): split_offsets = [] split_offsets.append(timespan.start_offset - self.start_offset) split_offsets.append(timespan.duration) result = self._split_payload_at_offsets(split_offsets) middle_payload = result[1] middle_timespan = timespantools.Timespan(*timespan.offsets) middle_payload_expression = type(self)( payload=[], start_offset=middle_timespan.start_offset, voice_name=self.voice_name, ) middle_payload_expression._payload = middle_payload result = timespantools.TimespanInventory( [middle_payload_expression]) else: result = timespantools.TimespanInventory() return result
def _get_timespan_delimited_single_context_set_expressions( self, attribute): result = timespantools.TimespanInventory() for context_proxy in \ self.score_specification.single_context_set_expressions_by_context.values(): expressions = \ context_proxy.timespan_delimited_single_context_set_expressions_by_attribute[attribute] for timespan_delimited_single_context_set_expression in expressions: if not timespan_delimited_single_context_set_expression.source_expression == self: result.append( timespan_delimited_single_context_set_expression) return result
def __or__(self, set_expression): r'''Logical OR of timespan-delimited single-context set expression and `set_expression`. Raises exception when timespan-delimited single-context set expression can not fuse with `set_expression`. Returns timespan inventory. ''' assert self._can_fuse(set_expression) stop_offset = self.target_timespan.stop_offset + \ set_expression.target_timespan.duration target_timespan = new(self.target_timespan, stop_offset=stop_offset) result = new(self, target_timespan=target_timespan) return timespantools.TimespanInventory([result])
def evaluate(self): r'''Evaluate counttime component select expression. Returns none when nonevaluable. Returns start-positioned rhythm payload expression when evaluable. ''' from experimental.tools import musicexpressiontools anchor_timespan = self._evaluate_anchor_timespan() voice_proxy = \ self.score_specification.voice_data_structures_by_voice[ self.voice_name] rhythm_payload_expressions = \ voice_proxy.payload_expressions_by_attribute['rhythm'] # TODO: will this have to be optimized with bisect? rhythm_payload_expressions = \ rhythm_payload_expressions.get_timespans_that_satisfy_time_relation( timespantools.timespan_2_intersects_timespan_1( timespan_1=anchor_timespan)) if not rhythm_payload_expressions: return rhythm_payload_expressions = \ copy.deepcopy(rhythm_payload_expressions) rhythm_payload_expressions = \ timespantools.TimespanInventory(rhythm_payload_expressions) rhythm_payload_expressions.sort() assert anchor_timespan.is_well_formed, repr(anchor_timespan) rhythm_payload_expressions &= anchor_timespan expression = \ musicexpressiontools.StartPositionedRhythmPayloadExpression( start_offset=anchor_timespan.start_offset) for rhythm_payload_expression in rhythm_payload_expressions: expression.payload.extend(rhythm_payload_expression.payload) assert inspect_(expression.payload).is_well_formed() # TODO: eventually make this be able to work #callback_cache = self.score_specification.interpreter.callback_cache #expression = expression.get_elements_that_satisfy_time_relation( # time_relation, callback_cache) expression = self._apply_callbacks(expression) expression._voice_name = self.voice_name return expression
def get_offset_indices( self, timespan_1, timespan_2_start_offsets, timespan_2_stop_offsets, ): r'''Gets offset indices of compound inequality. ''' from abjad.tools import timespantools from abjad.tools import timespantools timespans = timespantools.TimespanInventory() for element in self: # TODO: compress the following two branches if isinstance(element, type(self)): result = element.get_offset_indices(timespan_1, timespan_2_start_offsets, timespan_2_stop_offsets) timespans.extend(result) elif isinstance(element, timespantools.Inequality): offset_indices = element.get_offset_indices( timespan_1, timespan_2_start_offsets, timespan_2_stop_offsets) timespan = timespantools.Timespan(*offset_indices) timespans.append(timespan) else: message = 'unknown inequality: {!r}.' message = message(element) raise TypeError(message) if self.logical_operator == 'and': result = timespans.compute_logical_and() elif self.logical_operator == 'or': timespans.sort() result = timespans.compute_logical_or() elif self.logical_operator == 'xor': result = timespans.compute_logical_xor() else: message = 'unknown logical operator: {!r}.' message = mesage.format(self.logical_operator) raise ValueError(message) return result
def __init__(self): #collections.OrderedDict.__init__(self) datastructuretools.TypedOrderedDict.__init__(self) for attribute in self.attributes: self[attribute] = timespantools.TimespanInventory() assert 'time_signatures' in self
def __illustrate__(self, denominator=16, range_=None, scale=None): r'''Illustrates meter inventory. .. container:: example :: >>> meter_inventory = metertools.MeterInventory([ ... (3, 4), (5, 16), (7, 8), ... ]) >>> show(meter_inventory, scale=0.5) # doctest: +SKIP .. doctest >>> illustration = meter_inventory.__illustrate__() >>> print(format(illustration)) % ... <BLANKLINE> \version "..." \language "english" <BLANKLINE> \header { tagline = \markup {} } <BLANKLINE> \layout {} <BLANKLINE> \paper {} <BLANKLINE> \markup { \column { \combine \combine \translate #'(1.0 . 1) \sans \fontsize #-3 \center-align \fraction 3 4 \translate #'(49.387... . 1) \sans \fontsize #-3 \center-align \fraction 5 16 \translate #'(69.548... . 1) \sans \fontsize #-3 \center-align \fraction 7 8 \combine \postscript #" 0.2 setlinewidth 1 0.5 moveto 49.387... 0.5 lineto stroke 1 1.25 moveto 1 -0.25 lineto stroke 49.387... 1.25 moveto 49.387... -0.25 lineto stroke 49.387... 0.5 moveto 69.548... 0.5 lineto stroke 49.387... 1.25 moveto 49.387... -0.25 lineto stroke 69.548... 1.25 moveto 69.548... -0.25 lineto stroke 69.548... 0.5 moveto 126 0.5 lineto stroke 69.548... 1.25 moveto 69.548... -0.25 lineto stroke 126 1.25 moveto 126 -0.25 lineto stroke " \postscript #" 1 -2 moveto 0 -6.153... rlineto stroke 5.032... -2 moveto 0 -1.538... rlineto stroke 9.064... -2 moveto 0 -3.076... rlineto stroke 13.096... -2 moveto 0 -1.538... rlineto stroke 17.129... -2 moveto 0 -4.615... rlineto stroke 21.161... -2 moveto 0 -1.538... rlineto stroke 25.193... -2 moveto 0 -3.076... rlineto stroke 29.225... -2 moveto 0 -1.538... rlineto stroke 33.258... -2 moveto 0 -4.615... rlineto stroke 37.290... -2 moveto 0 -1.538... rlineto stroke 41.322... -2 moveto 0 -3.076... rlineto stroke 45.354... -2 moveto 0 -1.538... rlineto stroke 49.387... -2 moveto 0 -6.153... rlineto stroke 49.387... -2 moveto 0 -10.909... rlineto stroke 53.419... -2 moveto 0 -3.636... rlineto stroke 57.451... -2 moveto 0 -3.636... rlineto stroke 61.483... -2 moveto 0 -7.272... rlineto stroke 65.516... -2 moveto 0 -3.636... rlineto stroke 69.548... -2 moveto 0 -10.909... rlineto stroke 69.548... -2 moveto 0 -5.517... rlineto stroke 73.580... -2 moveto 0 -1.379... rlineto stroke 77.612... -2 moveto 0 -2.758... rlineto stroke 81.645... -2 moveto 0 -1.379... rlineto stroke 85.677... -2 moveto 0 -2.758... rlineto stroke 89.709... -2 moveto 0 -1.379... rlineto stroke 93.741... -2 moveto 0 -4.137... rlineto stroke 97.774... -2 moveto 0 -1.379... rlineto stroke 101.806... -2 moveto 0 -2.758... rlineto stroke 105.838... -2 moveto 0 -1.379... rlineto stroke 109.870... -2 moveto 0 -4.137... rlineto stroke 113.903... -2 moveto 0 -1.379... rlineto stroke 117.935... -2 moveto 0 -2.758... rlineto stroke 121.967... -2 moveto 0 -1.379... rlineto stroke 126 -2 moveto 0 -5.517... rlineto stroke " } } Returns LilyPond file. ''' from abjad.tools import metertools durations = [_.duration for _ in self] total_duration = sum(durations) offsets = mathtools.cumulative_sums(durations, start=0) timespan_inventory = timespantools.TimespanInventory() for one, two in sequencetools.iterate_sequence_nwise(offsets): timespan = timespantools.Timespan( start_offset=one, stop_offset=two, ) timespan_inventory.append(timespan) if range_ is not None: minimum, maximum = range_ else: minimum, maximum = 0, total_duration minimum = float(durationtools.Offset(minimum)) maximum = float(durationtools.Offset(maximum)) if scale is None: scale = 1. assert 0 < scale postscript_scale = 125. / (maximum - minimum) postscript_scale *= float(scale) postscript_x_offset = (minimum * postscript_scale) - 1 timespan_markup = timespan_inventory._make_timespan_inventory_markup( timespan_inventory, postscript_x_offset, postscript_scale, draw_offsets=False, ) ps = markuptools.Postscript() rational_x_offset = durationtools.Offset(0) for meter in self: kernel_denominator = denominator or meter.denominator kernel = metertools.MetricAccentKernel.from_meter( meter, kernel_denominator) for offset, weight in sorted(kernel.kernel.items()): weight = float(weight) * -40 ps_x_offset = float(rational_x_offset + offset) ps_x_offset *= postscript_scale ps_x_offset += 1 ps = ps.moveto(ps_x_offset, -2) ps = ps.rlineto(0, weight) ps = ps.stroke() rational_x_offset += meter.duration ps = markuptools.Markup.postscript(ps) lines_markup = markuptools.Markup.combine(timespan_markup, ps) fraction_markups = [] for meter, offset in zip(self, offsets): numerator, denominator = meter.numerator, meter.denominator fraction = markuptools.Markup.fraction(numerator, denominator) fraction = fraction.center_align().fontsize(-3).sans() x_translation = (float(offset) * postscript_scale) x_translation -= postscript_x_offset fraction = fraction.translate((x_translation, 1)) fraction_markups.append(fraction) fraction_markup = fraction_markups[0] for markup in fraction_markups[1:]: fraction_markup = markuptools.Markup.combine( fraction_markup, markup) markup = markuptools.Markup.column([fraction_markup, lines_markup]) return markup.__illustrate__()