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_array
in 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.
False
by 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_indices
but 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
data
fromget_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.Counter
Class 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