Source code for tsmakers.TimespanMaker

import abc
import collections

import abjad

from .CompositeMusicSpecifier import CompositeMusicSpecifier
from .MusicSpecifierSequence import MusicSpecifierSequence
from .PerformedTimespan import PerformedTimespan
from .SilentTimespan import SilentTimespan
from .TimespanSpecifier import TimespanSpecifier


[docs]class TimespanMaker(object): r""" Abstract base class for timespan makers. """ ### CLASS VARIABLES ### __slots__ = ( "_output_masks", "_padding", "_seed", "_timespan_specifier", ) ### INITIALIZER ### @abc.abstractmethod def __init__( self, division_masks=None, padding=None, seed=None, timespan_specifier=None, ): if division_masks is not None: if isinstance(division_masks, abjad.Pattern): division_masks = (division_masks,) division_masks = abjad.PatternTuple( items=division_masks, ) self._output_masks = division_masks if padding is not None: padding = abjad.Duration(padding) self._padding = padding if seed is not None: seed = int(seed) self._seed = seed if timespan_specifier is not None: assert isinstance(timespan_specifier, TimespanSpecifier) self._timespan_specifier = timespan_specifier ### SPECIAL METHODS ###
[docs] def __call__( self, layer=None, music_specifiers=None, rotation=None, silenced_context_names=None, target_timespan=None, timespan_list=None, ): if not isinstance(timespan_list, abjad.TimespanList): timespan_list = abjad.TimespanList( timespan_list, ) if target_timespan is None: if timespan_list: target_timespan = timespan_list.timespan else: raise TypeError assert isinstance(timespan_list, abjad.TimespanList) if not music_specifiers: return timespan_list music_specifiers = self._coerce_music_specifiers(music_specifiers) new_timespans = self._make_timespans( layer=layer, music_specifiers=music_specifiers, target_timespan=target_timespan, timespan_list=timespan_list, ) self._cleanup_silent_timespans( layer=layer, silenced_context_names=silenced_context_names, timespans=new_timespans, ) timespan_list.extend(new_timespans) timespan_list.sort() return timespan_list
[docs] def __illustrate__(self, scale=None, target_timespan=None, **kwargs): target_timespan = target_timespan or abjad.Timespan(0, 16) assert isinstance(target_timespan, abjad.Timespan) assert 0 < target_timespan.duration scale = scale or 1.5 music_specifiers = abjad.OrderedDict( [ ("A", "A music"), ("B", "B music"), ("C", "C music"), ("D", "D music"), ("E", "E music"), ("F", "F music"), ("G", "G music"), ("H", "H music"), ("I", "I music"), ("J", "J music"), ] ) timespan_list = self( layer=0, music_specifiers=music_specifiers, target_timespan=target_timespan, ) ti_lilypond_file = timespan_list.__illustrate__( key="voice_name", range_=target_timespan, scale=scale, ) ti_markup = ti_lilypond_file.items[-1] offset_counter = abjad.OffsetCounter(timespan_list) oc_lilypond_file = offset_counter.__illustrate__( range_=target_timespan, scale=scale, ) oc_markup = oc_lilypond_file.items[-1] lilypond_file = abjad.LilyPondFile.new( default_paper_size=["tabloid", "landscape"], date_time_token=False, ) lilypond_file.items.extend( [ abjad.String.normalize( """ % Backport for pre 2.19.20 versions of LilyPond #(define-markup-command (overlay layout props args) (markup-list?) (apply ly:stencil-add (interpret-markup-list layout props args))) """ ), ti_markup, abjad.Markup.null().pad_around(2), oc_markup, ] ) lilypond_file.header_block.tagline = False return lilypond_file
[docs] def __format__(self, format_specification=""): return abjad.storage(self)
[docs] def __str__(self): return abjad.storage(self)
[docs] def __repr__(self): return abjad.storage(self)
### PRIVATE METHODS ### @staticmethod def _coerce_music_specifiers(music_specifiers): # from MusicSpecifier import MusicSpecifier # from MusicSpecifierSequence import MusicSpecifierSequence result = collections.OrderedDict() prototype = ( MusicSpecifierSequence, CompositeMusicSpecifier, ) for context_name, music_specifier in music_specifiers.items(): if music_specifier is None: music_specifier = [None] if not isinstance(music_specifier, prototype): music_specifier = MusicSpecifierSequence( music_specifiers=music_specifier, ) result[context_name] = music_specifier return result def _cleanup_silent_timespans( self, layer, silenced_context_names, timespans, ): if not silenced_context_names or not timespans: return silent_timespans_by_context = {} for context_name in silenced_context_names: if context_name not in silent_timespans_by_context: silent_timespans_by_context[context_name] = abjad.TimespanList() sounding_timespans_by_context = {} sounding_timespans = abjad.TimespanList() for timespan in timespans: voice_name = timespan.voice_name if isinstance(timespan, PerformedTimespan): if voice_name not in sounding_timespans_by_context: sounding_timespans_by_context[voice_name] = abjad.TimespanList() sounding_timespans_by_context[voice_name].append(timespan) sounding_timespans.append(timespan) else: if voice_name not in silent_timespans_by_context: silent_timespans_by_context[voice_name] = abjad.TimespanList() silent_timespans_by_context[voice_name].append(timespan) sounding_timespans.sort() sounding_timespans.compute_logical_or() # Create silences. for shard in sounding_timespans.partition(True): for context_name in silenced_context_names: timespan = SilentTimespan( layer=layer, voice_name=context_name, start_offset=shard.start_offset, stop_offset=shard.stop_offset, ) silent_timespans_by_context[context_name].append(timespan) # Remove any overlap between performed and silent timespans. # Then add the silent timespans into the original timespan inventory. for context_name, silent_timespans in sorted( silent_timespans_by_context.items() ): silent_timespans.sort() if context_name in sounding_timespans_by_context: for timespan in sounding_timespans_by_context[context_name]: silent_timespans - timespan timespans.extend(silent_timespans) ### PUBLIC METHODS ###
[docs] def rotate(self, rotation): seed = self.seed or 0 seed = seed + rotation return abjad.new(self, seed=seed)
### PUBLIC PROPERTIES ### @property def is_dependent(self): return False @property def division_masks(self): return self._output_masks @property def padding(self): return self._padding @property def seed(self): return self._seed @property def timespan_specifier(self): return self._timespan_specifier