utils¶
- 
decitala.utils.get_logger(name, print_to_console=True, write_to_file=None)[source]¶ A simple helper for logging.
- Parameters
 name (str) – name of the logging object to be created.
print_to_console (bool) – whether to print the logs to the console.
write_to_file (str) – optional filepath to save the logs to.
- 
decitala.utils.carnatic_string_to_ql_array(string_)[source]¶ - Parameters
 string (str) – A string of carnatic durations separated by spaces.
- Returns
 The input string converted to a quarter length array.
- Return type
 numpy.array.
>>> carnatic_string_to_ql_array('oc o | | Sc S o o o') array([0.375, 0.25 , 0.5 , 0.5 , 1.5 , 1. , 0.25 , 0.25 , 0.25 ])
- 
decitala.utils.ql_array_to_carnatic_string(ql_array)[source]¶ - Parameters
 ql_array – A quarter length array.
- Returns
 The quarter length array converted to carnatic notation.
- Return type
 str
>>> ql_array_to_carnatic_string([0.5, 0.25, 0.25, 0.375, 1.0, 1.5, 1.0, 0.5, 1.0]) '| o o oc S Sc S | S'
- 
decitala.utils.ql_array_to_greek_diacritics(ql_array)[source]¶ Returns the input
ql_arrayin greek prosodic notation. This notation only allows for two types of rhythmic values (long & short).- Parameters
 ql_array – A quarter length array.
- Returns
 The quarter length array converted to greek prosodic notation.
- Return type
 str
>>> ql_array_to_greek_diacritics(ql_array=[1.0, 0.5, 0.5, 1.0, 1.0, 0.5]) '–– ⏑ ⏑ –– –– ⏑'
- 
decitala.utils.roll_window(array, window_size, fn=None)[source]¶ Takes in a list and returns a numpy vstack holding rolling windows of length
window_size.- Parameters
 array – a list, tuple, numpy array, etc.
window_size (int) – size of the window
fn (lambda) – a function evaluating a bool; will only iterate over elements satifying a condition.
- Returns
 A rolling windows of array, each of length window_size.
- Return type
 numpy.vstack
>>> composers = np.array(['Mozart', 'Monteverdi', 'Messiaen', 'Mahler', 'MacDowell', 'Massenet']) >>> for window in roll_window(array=composers, window_size=3): ... print(window) ('Mozart', 'Monteverdi', 'Messiaen') ('Monteverdi', 'Messiaen', 'Mahler') ('Messiaen', 'Mahler', 'MacDowell') ('Mahler', 'MacDowell', 'Massenet') >>> contour_extrema = [[0, {1, -1}], [4, {1}], [2, {-1}], [5, {1}], [5, {1}], [1, {1, -1}]] >>> max_check = lambda x: 1 in x[1] >>> for this_frame in roll_window(contour_extrema, window_size=3, fn=max_check): ... print(this_frame) ([0, {1, -1}], [4, {1}], [5, {1}]) ([4, {1}], [5, {1}], [5, {1}]) ([5, {1}], [5, {1}], [1, {1, -1}])
- 
decitala.utils.power_list(data)[source]¶ - Parameters
 data – an iterable
- Returns
 power set of the data as a list (excluding the empty list).
- Return type
 list
>>> l = [1, 2, 3] >>> power_list(l) [(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
>>> for x in power_list([(0.0, 2.0), (4.0, 5.5), (6.0, 7.25)]): ... print(x) ((0.0, 2.0),) ((4.0, 5.5),) ((6.0, 7.25),) ((0.0, 2.0), (4.0, 5.5)) ((0.0, 2.0), (6.0, 7.25)) ((4.0, 5.5), (6.0, 7.25)) ((0.0, 2.0), (4.0, 5.5), (6.0, 7.25))
- 
decitala.utils.get_shells(data)[source]¶ - Parameters
 data – an iterable
- Returns
 a list holding tuples. Each tuple holds the shells in outer-to-inner order. If the data holds an odd number of elements, the central element is returned as a singleton.
- Return type
 list
>>> l = [1, 2, 3, 4] >>> get_shells(l) [(1, 4), (2, 3)] >>> l2 = [('bob', 1), ('sue', 2), ('andrew', 3), ('luke', 4), ('alex', 5)] >>> get_shells(l2) [(('bob', 1), ('alex', 5)), (('sue', 2), ('luke', 4)), (('andrew', 3),)]
- 
decitala.utils.augment(ql_array, factor=1.0, difference=0.0)[source]¶ Returns an augmentation in the style of Messiaen. If difference is set to 0.0, then the augmentation is multiplicative. If factor is set to 1.0, then augmentation is additive. If factor & difference are non-zero, we have a mixed augmentation.
- Parameters
 ql_array – A quarter length array.
factor (float) – The factor for multiplicative augmentation.
difference (float) – The factor for additive augmentation.
- Returns
 The fragment augmented by the given factor and difference.
- Return type
 numpy.array
>>> augment(ql_array=[1.0, 1.0, 0.5, 0.25], factor=2.0, difference=0.25) array([2.25, 2.25, 1.25, 0.75])
- 
decitala.utils.stretch_augment(ql_array, factor, stretch_factor)[source]¶ A special kind of rhythmic augmentation catered toward the Greek metrics. The “short” is kept as is and the “long” is modified by the given difference. The new long must still be longer than the short value.
- Parameters
 ql_array – A quarter length array.
>>> stretch_augment(ql_array=[1.0, 2.0], factor=0.125, stretch_factor=0.25) array([0.125, 0.5 ])
- 
decitala.utils.successive_ratio_array(ql_array)[source]¶ Returns array defined by the ratio of successive elements. By convention, we set the first value to 1.0.
- Parameters
 ql_array – A quarter length array.
- Returns
 An array consisting of successive ratios of the input elements.
- Return type
 numpy.array
>>> successive_ratio_array([1.0, 1.0, 2.0, 0.5, 0.5, 0.25, 1.0]) array([1. , 1. , 2. , 0.25, 1. , 0.5 , 4. ])
- 
decitala.utils.successive_difference_array(ql_array)[source]¶ Returns the first order difference of
ql_array(contiguous differences).- Parameters
 ql_array – A quarter length array.
- Returns
 An array consisting of successive differences of the input elements.
- Return type
 numpy.array
>>> successive_difference_array([0.25, 0.25, 0.75, 0.75, 0.5, 1.0, 1.5]) array([ 0. , 0. , 0.5 , 0. , -0.25, 0.5 , 0.5 ])
- 
decitala.utils.dseg(ql_array, reduced=False, as_str=False)[source]¶ - Parameters
 reduced (bool) – Whether to remove equal contiguous values.
as_str (bool) – Whether to make the return type a string.
- Returns
 The d-seg of the fragment, as introducted in The Perception of Rhythm in Non-Tonal Music (Marvin, 1991). Maps a fragment into a sequence of relative durations.
- Return type
 numpy.array (or string if as_str=True).
>>> g3 = fragment.GeneralFragment(np.array([0.25, 0.75, 2.0, 1.0]), name='marvin-p70') >>> g3.dseg() array([0, 1, 3, 2])
- 
decitala.utils.non_retrogradable_measures(filepath, part_num)[source]¶ Function for retrieving all non-retrogradable measures in a given filepath and part number.
- 
decitala.utils.find_clusters(input_, data_mode=False)[source]¶ Finds the regions with consecutive equal elements.
- Parameters
 input (iterable) – Either a list/array (representing
ql_array) or data fromget_object_indices.data_mode (bool) – whether the input data is data from
get_object_indices.
- Returns
 a list of cluster indices; if not in data mode, regions with equal quarter length values; if
data_mode=True, then regions where the quarter lengths and pitch content are equal.
>>> varied_ragavardhana = np.array([1, 1, 1, 0.5, 0.75, 0.75, 0.5, 0.25, 0.25, 0.25]) >>> clusters = find_clusters(varied_ragavardhana) >>> clusters [[0, 2], [4, 5], [7, 9]] >>> varied_ragavardhana[clusters[0][0]:clusters[0][1]+1] array([1., 1., 1.]) >>> varied_ragavardhana[clusters[1][0]:clusters[1][1]+1] array([0.75, 0.75]) >>> varied_ragavardhana[clusters[2][0]:clusters[2][1]+1] array([0.25, 0.25, 0.25]) >>> # We can also find clusters of pitch and rhythmic information for data from get_object_indices. >>> from music21 import note, chord >>> example_data = [ ... (note.Note("F#"), (6.5, 6.75)), ... (note.Note("G"), (6.75, 7.0)), ... (note.Note("G"), (7.0, 7.25)), ... (note.Note("C#"), (7.25, 7.5)), ... (note.Note("G"), (7.5, 7.75)), ... (note.Note("G"), (7.75, 8.0)), ... (note.Note("A-"), (8.0, 8.125)), ... ] >>> find_clusters(example_data, data_mode=True) [[1, 2], [4, 5]] >>> example_data2 = [ ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.0, 0.125)), ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.125, 0.25)), ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.25, 0.375)), ... (chord.Chord(["E-3", "D4"], quarterLength=0.125), (0.375, 0.5)), ... (chord.Chord(["A2", "A-3"], quarterLength=0.25), (0.5, 0.75)), ... ] >>> find_clusters(example_data2, data_mode=True) [[0, 2]]
- 
decitala.utils.find_possible_superdivisions(ql_array, include_self=True)[source]¶ There is a more general approach to the subdivision problem, but we note that Messiaen’s subdivision of tala components tends to be even.
>>> long_fragment = np.array([1, 1, 1, 0.5, 0.75, 0.75, 0.5, 0.25, 0.25, 0.25]) >>> for x in find_possible_superdivisions(long_fragment): ... print(x) [1. 1. 1. 0.5 0.75 0.75 0.5 0.25 0.25 0.25] [3. 0.5 0.75 0.75 0.5 0.25 0.25 0.25] [1. 1. 1. 0.5 1.5 0.5 0.25 0.25 0.25] [1. 1. 1. 0.5 0.75 0.75 0.5 0.75] [3. 0.5 1.5 0.5 0.25 0.25 0.25] [3. 0.5 0.75 0.75 0.5 0.75] [1. 1. 1. 0.5 1.5 0.5 0.75] [3. 0.5 1.5 0.5 0.75]
>>> varied_ragavardhana = np.array([1, 1, 1, 0.5, 0.75, 0.5]) >>> for x in find_possible_superdivisions(varied_ragavardhana, include_self=False): ... print(x) [3. 0.5 0.75 0.5 ]
- 
decitala.utils.net_ql_array(filepath, part_num, include_rests=False, ignore_grace_notes=True)[source]¶ Function for retrieving all quarter lengths from a part number in a filepath.
- 
decitala.utils.transform_to_time_scale(ql_array)[source]¶ Transforms a quarter length array to time-scale (binary) notation.
- Parameters
 ql_array – A quarter length array.
>>> udikshana = fragment.Decitala("Udikshana") >>> udikshana.ql_array() array([0.5, 0.5, 1. ]) >>> transform_to_time_scale(ql_array=udikshana.ql_array()) array([1, 1, 1, 0])
- 
decitala.utils.get_object_indices(filepath, part_num, measure_divider_mode=None, ignore_grace=False)[source]¶ Returns data of the form [(object, (start, end)), …] for a given file path and part number. (Supports rests and grace notes.)
- Parameters
 filepath (str) – Path to file to be analyzed.
part_num (int) – Part number to be analyzed.
measure_divider_mode (str) – Tool used for dividing the data into measures. If
measure_divider_mode="str", the data is returned with"B"used as the measure marker. If insteadmeasure_divider_mode="list", the data is returned partitioned by measure. The default isNone, so no measure divisions are present.ignore_grace (bool) – Whether to ignore grace notes in the output.
Falseby default.
- 
decitala.utils.phrase_divider(filepath, part_num)[source]¶ This is an oversimplified but useful tool for phrase analysis (particularly for the birdsongs). It returns the same output as
decitala.utils.get_object_indicesbut divides the output by “phrases,” only as defined by the appearance of rests and fermatas. Ignores all dividers.- Parameters
 filepath (str) – Path to file to be analyzed.
part_num (int) – Part number to be analyzed.
- 
decitala.utils.reframe_ts(ts, new_denominator=None)[source]¶ Function for reducing a music21.meter.TimeSignature object (lowest denominator of 1) to a given denominiator.
- Parameters
 ts – A music21.meter.TimeSignature object.
- Returns
 A new time signature that is fully reduced by removing all possible powers of 2.
- Return type
 music21.meter.TimeSignature
>>> from music21.meter import TimeSignature >>> reframe_ts(TimeSignature("4/16")) <music21.meter.TimeSignature 1/4> >>> reframe_ts(TimeSignature("4/4"), new_denominator=2) <music21.meter.TimeSignature 2/2>
- 
decitala.utils.rolling_SRR(filepath, part_num, window_size, ignore_tuplets=True)[source]¶ Given a filepath, part number, and window size, extracts all notes/chords in the work and, on a rolling window, calculates the successive ratio representation (SRR) of each window. Returning the results as a list.
- Parameters
 filepath (str) – Path to file to be analyzed.
part_num (int) – Part number to be analyzed.
window_size (int) – Window size used in the calculations.
ignore_tuplets (bool) – Whether to ignore tuplets in the output. The use of tuplets will add some erroneous ratios to the data. Default is
True.
- Returns
 List holding successive ratio representations of each window on a rolling window of size
window_size.- Return type
 list
- 
decitala.utils.contiguous_summation(data)[source]¶ Given some
datafromget_object_indices, finds every location where the pitch and rhythmic material are contiguously equal and sums these regions.>>> from music21 import note, chord >>> example_data = [ ... (note.Note("F#"), (6.5, 6.75)), ... (note.Note("G"), (6.75, 7.0)), ... (note.Note("G"), (7.0, 7.25)), ... (note.Note("C#"), (7.25, 7.5)), ... (note.Note("G"), (7.5, 7.75)), ... (note.Note("G"), (7.75, 8.0)), ... (note.Note("A-"), (8.0, 8.125)), ... ] >>> for this_object in contiguous_summation(example_data): ... print(this_object) (<music21.note.Note F#>, (6.5, 6.75)) (<music21.note.Note G>, (6.75, 7.25)) (<music21.note.Note C#>, (7.25, 7.5)) (<music21.note.Note G>, (7.5, 8.0)) (<music21.note.Note A->, (8.0, 8.125)) >>> # Also works with chords. >>> example_data2 = [ ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.0, 0.125)), ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.125, 0.25)), ... (chord.Chord(["F#2", "F3"], quarterLength=0.125), (0.25, 0.375)), ... (chord.Chord(["E-3", "D4"], quarterLength=0.125), (0.375, 0.5)), ... (chord.Chord(["A2", "A-3"], quarterLength=0.25), (0.5, 0.75)), ... ] >>> sum_search = contiguous_summation(example_data2) >>> for this_object in sum_search: ... print(this_object) (<music21.chord.Chord F#2 F3>, (0.0, 0.375)) (<music21.chord.Chord E-3 D4>, (0.375, 0.5)) (<music21.chord.Chord A2 A-3>, (0.5, 0.75)) >>> # The quarter lengths of the objects change according to the new summation. >>> for this_object in sum_search: ... print(this_object[0].quarterLength) 0.375 0.125 0.25
- 
decitala.utils.filter_single_anga_class_fragments(data)[source]¶ - Parameters
 data (list) – data from
rolling_search.- Returns
 data from the input with all single-anga-class talas removed. For information on anga-class, see:
num_anga_classes.- Return type
 list
>>> from decitala.fragment import GreekFoot >>> data = [ ... {'fragment': GreekFoot("Spondee"), 'mod': ('r', 0.125), 'onset_range': (0.0, 0.5), 'is_spanned_by_slur': False, 'pitch_content': [(80,), (91,)]}, # noqa: E501 ... {'fragment': GreekFoot("Trochee"), 'mod': ('r', 0.125), 'onset_range': (0.25, 0.625), 'is_spanned_by_slur': False, 'pitch_content': [(91,), (78,)]}, ... {'fragment': GreekFoot("Spondee"), 'mod': ('r', 0.0625), 'onset_range': (0.5, 0.75), 'is_spanned_by_slur': False, 'pitch_content': [(78,), (85,)]}, ... {'fragment': GreekFoot("Iamb"), 'mod': ('r', 0.125), 'onset_range': (0.625, 1.0), 'is_spanned_by_slur': False, 'pitch_content': [(85,), (93,)]}, ... {'fragment': GreekFoot("Spondee"), 'mod': ('r', 0.125), 'onset_range': (0.75, 1.25), 'is_spanned_by_slur': False, 'pitch_content': [(93,), (91,)]} ... ] >>> filtered = filter_single_anga_class_fragments(data) >>> for x in filtered: ... print(x) {'fragment': <fragment.GreekFoot Trochee>, 'mod': ('r', 0.125), 'onset_range': (0.25, 0.625), 'is_spanned_by_slur': False, 'pitch_content': [(91,), (78,)]} {'fragment': <fragment.GreekFoot Iamb>, 'mod': ('r', 0.125), 'onset_range': (0.625, 1.0), 'is_spanned_by_slur': False, 'pitch_content': [(85,), (93,)]}
- 
decitala.utils.filter_sub_fragments(data, filter_in_retrograde=True)[source]¶ - Parameters
 data (list) – data from
rolling_search.- Returns
 data from the input with all sub-talas removed; that is, talas that sit inside of another.
- Return type
 list
- 
decitala.utils.measure_by_measure_time_signatures(filepath)[source]¶ Returns list of meter.TimeSignature objects from music21 for each measure of an input stream.
- 
decitala.utils.loader(filepath)[source]¶ Useful function for loading analyses into native python format (from a json).
- Parameters
 filepath (str) – path to analysis file in the databases/analyses directory.
- Returns
 analysis in native python types. Fragments and their associated onset range.
- Return type
 list
- 
class 
decitala.utils.NormalizedCounter(iterable, count=False)[source]¶ Bases:
collections.CounterClass that inherits from collections.Counter. Takes in an array-like object, but the values of the ‘counter’ become proportions, unless count is set to True (in which case it acts like a regular counter).
>>> l = [1, 1, 2, 2, 3, 3, 4, 4] >>> NormalizedCounter(l, count=True) NormalizedCounter({1: 2, 2: 2, 3: 2, 4: 2}) >>> NormalizedCounter(l, count=False) NormalizedCounter({1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25})
- 
decitala.utils.dict_to_ordered_dict(dict_in, key, reverse=True)[source]¶ Takes in a dict and returns an OrderedDict object sorted by a given key (in the form of a lambda expression).
- Parameters
 dict_in (dict) – a dictionary to be turned into an ordered dictionary.
key – lambda expression.
reverse (bool) – whether to sort the dict in reverse.
- Returns
 the dictionary input, ordered by the given key.
- Return type
 collections.OrderedDict