Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Py3 #78

Merged
merged 5 commits into from
Feb 18, 2018
Merged

Py3 #78

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions tomato/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
# PhD thesis, Universitat Pompeu Fabra, Barcelona, Spain.

from abc import ABCMeta, abstractmethod, abstractproperty
from io import IO
from six import iteritems
from .io import IO
import logging
import warnings

Expand Down Expand Up @@ -73,7 +72,7 @@ def _parse_inputs(self, **kwargs):
# initialize precomputed_features with the available analysis
precomputed_features = dict((f, None)
for f in self._inputs)
for feature, val in iteritems(kwargs):
for feature, val in kwargs.items():
if feature not in self._inputs:
warn_str = u'Unrelated feature {0:s}: It will be kept, ' \
u'but it will not be used in the audio analysis.' \
Expand Down
5 changes: 2 additions & 3 deletions tomato/audio/ahenk.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
# PhD thesis, Universitat Pompeu Fabra, Barcelona, Spain.

import numpy as np
from future.utils import iteritems
from ..io import IO


Expand Down Expand Up @@ -70,7 +69,7 @@ def identify(cls, tonic_freq, symbol_in):
'unit': 'cent'}}

# get the ahenk
for ahenk_slug, val in iteritems(ahenks):
for ahenk_slug, val in ahenks.items():
if val['cent_transposition'] == mod_cent_approx:
ahenk_dict['name'] = val['name']
ahenk_dict['slug'] = ahenk_slug
Expand All @@ -95,7 +94,7 @@ def _get_tonic_symbol(cls, symbol_in, tonic_dict):
@staticmethod
def _get_tonic_symbol_from_makam(symbol_in, tonic_dict):
tonic_bolahenk_freq = tonic_symbol = None
for sym, val in iteritems(tonic_dict):
for sym, val in tonic_dict.items():
if symbol_in in val['makams']:
tonic_symbol = sym
tonic_bolahenk_freq = val['bolahenk_freq']
Expand Down
9 changes: 7 additions & 2 deletions tomato/audio/audioanalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def _call_audio_metadata(self, audio_meta, filepath):
audio_meta = self.crawl_musicbrainz_metadata(audio_meta)
elif not isinstance(audio_meta, dict):
warn_str = 'The "metadata" input can be "False" (skipped), ' \
'"basestring" (MBID input), "None" (attempt to get ' \
'"str" (MBID input), "None" (attempt to get ' \
'the MBID from audio file tags) or "dict" (already ' \
'computed)'
warnings.warn(warn_str, stacklevel=2)
Expand All @@ -183,7 +183,12 @@ def _get_makam_tonic_training():
'models', 'makam_tonic_estimation',
'training_model--pcd--7_5--15_0--dlfm2016.pkl')

return pickle.load(open(makam_tonic_training_file))
try: # python 3
# the pickle was made via python 2, we have to specify the encoding
return pickle.load(open(makam_tonic_training_file, 'rb'),
encoding='latin1')
except TypeError: # python 2
return pickle.load(open(makam_tonic_training_file, 'rb'))

def crawl_musicbrainz_metadata(self, rec_in):
try:
Expand Down
12 changes: 7 additions & 5 deletions tomato/audio/notemodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _stable_pitches_to_notes(self, stable_pitches_hz,
for stable_pitch_cent, stable_pitch_hz in zip(stable_pitches_cent,
stable_pitches_hz):
note_cent = TonicLastNote.find_nearest(
theoretical_intervals.values(), stable_pitch_cent)
list(theoretical_intervals.values()), stable_pitch_cent)

if abs(stable_pitch_cent - note_cent) < self.pitch_threshold:
for key, val in theoretical_intervals.items():
Expand Down Expand Up @@ -124,7 +124,8 @@ def _get_theoretical_intervals_to_search(self, makam):

# Remove the notes neighboring the scale notes
keep_notes = natural_notes + key_signature
for note_name in note_dict.keys():
for note_name in list(note_dict.keys()): # get a copy to avoid
# mutating note_dict during iteration
if note_name in keep_notes:
if note_name[2:4] in ['b5', 'b4']:
rm_note_symbol = self.note_letters[
Expand Down Expand Up @@ -175,13 +176,14 @@ def _get_theoretical_intervals_to_search(self, makam):
def _get_natural_notes(self, key_signature, note_dict):
close_natural_notes = self._get_close_natural_notes(key_signature)
# get the natural notes that are not close to the key signature
natural_notes = [n for n in note_dict.keys() if len(n) == 2 and n
natural_notes = [n for n in list(note_dict.keys()) if len(n) == 2 and n
not in close_natural_notes]
return natural_notes

def _get_extended_key_signature(self, key_sig_in, note_dict):
key_signature = deepcopy(key_sig_in)
for note in note_dict.keys(): # extend the key signature to octaves
for note in list(note_dict.keys()): # extend the key signature to
# octaves
if any([self._is_same_pitch_class(note, ks)
for ks in key_signature]):
key_signature.append(note)
Expand Down Expand Up @@ -212,7 +214,7 @@ def plot(pitch_distribution, stable_notes):
matplotlib.ticker.FormatStrFormatter('%d'))
ax.set_xlim([min(pd_copy.bins), max(pd_copy.bins)])
ax.set_xticks([note['stable_pitch']['value']
for note in stable_notes.values()])
for note in list(stable_notes.values())])

# recording distribution
ax.plot(pd_copy.bins, pd_copy.vals,
Expand Down
2 changes: 1 addition & 1 deletion tomato/bincaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import os
import subprocess

from io import IO
from .io import IO


class BinCaller(object):
Expand Down
10 changes: 5 additions & 5 deletions tomato/joint/jointanalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import json
from scipy.io import savemat
from six.moves import cStringIO
from six import BytesIO
import tempfile
from copy import deepcopy
import timeit
Expand Down Expand Up @@ -192,7 +192,7 @@ def extract_tonic_tempo(self, score_filename='', score_data=None,
'.json', json.dumps(score_data))

# matlab
matout = cStringIO()
matout = BytesIO()
savemat(matout, audio_pitch)

temp_pitch_file = IO.create_temp_file(
Expand All @@ -207,7 +207,7 @@ def extract_tonic_tempo(self, score_filename='', score_data=None,
out, err = _mcr_caller.call(callstr)

# check the MATLAB output
if "Tonic-Tempo-Tuning Extraction took" not in out:
if "Tonic-Tempo-Tuning Extraction took" not in out.decode('utf-8'):
IO.remove_temp_files(
temp_score_data_file, temp_pitch_file, temp_out_folder)
raise RuntimeError("Score-informed tonic, tonic and tuning "
Expand Down Expand Up @@ -278,7 +278,7 @@ def align_audio_score(self, score_filename='', score_data=None,
'.json', json.dumps({'scoreInformed': audio_tempo_}))

# matlab
matout = cStringIO()
matout = BytesIO()
savemat(matout, audio_pitch)

temp_pitch_file = IO.create_temp_file(
Expand All @@ -297,7 +297,7 @@ def align_audio_score(self, score_filename='', score_data=None,
out, err = _mcr_caller.call(callstr)

# check the MATLAB output
if "Audio-score alignment took" not in out:
if "Audio-score alignment took" not in out.decode('utf-8'):
IO.remove_temp_files(
temp_score_data_file, temp_tonic_file, temp_tempo_file,
temp_pitch_file, temp_out_folder)
Expand Down
9 changes: 3 additions & 6 deletions tomato/metadata/recording.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from . work import Work
from . instrumentationvoicing import InstrumentationVoicing
import musicbrainzngs as mb
from six import iteritems
import logging
logging.basicConfig(level=logging.INFO)

Expand Down Expand Up @@ -60,9 +59,7 @@ def from_musicbrainz(self, audio_in):
audio_meta['url'] = u'http://musicbrainz.org/recording/{}'.format(
audio_meta['mbid'])

meta = mb.get_recording_by_id(
audio_meta['mbid'], includes=['artists', 'artist-rels', 'releases',
'tags', 'work-rels'])['recording']
meta = mb.get_recording_by_id(audio_meta['mbid'], includes=['artists', 'artist-rels', 'releases', 'tags', 'work-rels'])['recording']
audio_meta['title'] = meta['title']

# releases
Expand Down Expand Up @@ -106,7 +103,7 @@ def _get_attributes_from_works(self, audio_meta):
@staticmethod
def _get_recording_attribute_tags(audio_meta, meta):
attributetags = Attribute.get_attrib_tags(meta)
for key, vals in iteritems(attributetags):
for key, vals in attributetags.items():
for val in vals: # add the source
val['source'] = 'http://musicbrainz.org/recording/' + \
audio_meta['mbid']
Expand All @@ -121,7 +118,7 @@ def _get_recording_attribute_tags(audio_meta, meta):
def get_file_metadata(filepath):
audiofile = eyed3.load(filepath)
mbid = audiofile.tag.unique_file_ids.get(
'http://musicbrainz.org').data[-36:]
'http://musicbrainz.org').data[-36:].decode('utf-8')
duration = audiofile.info.time_secs
sampling_frequency = audiofile.info.sample_freq
bit_rate = audiofile.info.mp3_header.bit_rate
Expand Down
6 changes: 3 additions & 3 deletions tomato/metadata/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
# scores for the description and discovery of Ottoman-Turkish makam music.
# PhD thesis, Universitat Pompeu Fabra, Barcelona, Spain.

from . attribute import Attribute
import json
import warnings
import urllib
from six.moves.urllib.request import urlopen
from . attribute import Attribute

import musicbrainzngs as mb
mb.set_useragent("Makam corpus metadata", "1.2.0", "compmusic.upf.edu")
Expand Down Expand Up @@ -71,7 +71,7 @@ def from_musicbrainz(self, mbid):
def _add_scores(data, mbid):
score_work_url = 'https://raw.githubusercontent.com/MTG/SymbTr/' \
'master/symbTr_mbid.json'
response = urllib.urlopen(score_work_url)
response = urlopen(score_work_url)
score_work = json.loads(response.read())
data['scores'] = []
for sw in score_work:
Expand Down
7 changes: 3 additions & 4 deletions tomato/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import copy
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from six import iteritems
from matplotlib import gridspec
from matplotlib.ticker import FixedLocator

Expand Down Expand Up @@ -312,7 +311,7 @@ def _plot_note_models(cls, ax2, note_models, pitch_distribution):
@staticmethod
def _plot_stable_pitches(ax, max_rel_occur, note_models, max_pd_height):
ytick_vals = []
for note_symbol, note in iteritems(note_models):
for note_symbol, note in note_models.items():
plot_bool = (note['stable_pitch']['value'] and
note['rel_occur'] > max_rel_occur * 0.15)
if plot_bool:
Expand Down Expand Up @@ -346,7 +345,7 @@ def _plot_stable_pitches(ax, max_rel_occur, note_models, max_pd_height):
@staticmethod
def _get_relative_note_occurences(note_models, pitch_distribution):
max_rel_occur = 0
for note_symbol, note in iteritems(note_models):
for note_symbol, note in note_models.items():
try:
# get the relative occurrence of each note from the pitch
# distribution
Expand All @@ -370,7 +369,7 @@ def _get_relative_note_occurences(note_models, pitch_distribution):

@staticmethod
def _plot_note_distributions(ax, note_models):
for note_symbol, note in iteritems(note_models):
for note_symbol, note in note_models.items():
try:
ax.plot(note_models[note_symbol]['distribution'].vals,
note_models[note_symbol]['distribution'].bins,
Expand Down
51 changes: 26 additions & 25 deletions tomato/symbolic/musicxml2lilypond/musicxmlreader.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# coding=utf-8
from __future__ import unicode_literals, division
import warnings
import xml.etree.ElementTree as eT
from xml.etree.ElementTree import ParseError
from lxml import etree

__author__ = 'hsercanatli', 'burakuyar', 'andresferrero', 'sertansenturk'

Expand All @@ -25,15 +24,15 @@ def read(cls, xml_in):
"""

# setting the xml tree
parser = _XMLCommentHandler()
parser = etree.XMLParser(remove_comments=False)
try:
try: # document
tree = eT.parse(xml_in, parser)
tree = etree.parse(xml_in, parser)
root = tree.getroot()
except IOError: # string input
root = eT.fromstring(xml_in, parser)
except ParseError:
raise ParseError("Line 36(ish): Error parsing MusicXML file.")
root = etree.fromstring(xml_in, parser)
except etree.ParseError:
raise etree.ParseError("Line 36(?): Error parsing MusicXML file.")

# getting key signatures
keysig = cls._get_key_signature(root)
Expand All @@ -55,6 +54,7 @@ def read(cls, xml_in):

@staticmethod
def _get_key_signature(root):

keysig = {} # keys: notes, values: type of note accident
for xx, key in enumerate(
root.findall('part/measure/attributes/key/key-step')):
Expand Down Expand Up @@ -185,10 +185,12 @@ def _get_pitchstep_octave(note, rest):

@staticmethod
def _get_symbtr_txt_id(note):
if note.find("symbtrid").text:
return int(note.find("symbtrid").text)
else:
return None
for el in note:
if isinstance(el, etree._Comment):
comment_txt = el.text
if 'symbtr_txt_note_index' in comment_txt:
return int(comment_txt[len("symbtr_txt_note_index "):])
return None

@staticmethod
def _chk_rest(note):
Expand Down Expand Up @@ -225,17 +227,16 @@ def _get_lyrics(note):
else:
return ''


class _XMLCommentHandler(eT.XMLTreeBuilder):
def __init__(self):
super(_XMLCommentHandler, self).__init__()

# assumes ElementTree 1.2.X
self._parser.CommentHandler = self.handle_comment

def handle_comment(self, data):
self._target.start("symbtrid", {})
if data and 'symbtr_txt_note_index' in data:
data = data.replace('symbtr_txt_note_index ', '')
self._target.data(data)
self._target.end("symbtrid")
# class _XMLCommentHandler(XMLTreeBuilder):
# def __init__(self):
# super(_XMLCommentHandler, self).__init__()
#
# # assumes ElementTree 1.2.X
# self._parser.CommentHandler = self.handle_comment
#
# def handle_comment(self, data):
# self._target.start("symbtrid", {})
# if data and 'symbtr_txt_note_index' in data:
# data = data.replace('symbtr_txt_note_index ', '')
# self._target.data(data)
# self._target.end("symbtrid")
7 changes: 5 additions & 2 deletions tomato/symbolic/musicxml2lilypond/scoreconverter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coding=utf-8
from __future__ import unicode_literals, division
from musicxmlreader import MusicXMLReader
from .musicxmlreader import MusicXMLReader
import os
import sqlite3

Expand Down Expand Up @@ -256,6 +256,9 @@ def convert(cls, xml_in, ly_out=None, render_metadata=True):
# save to file
if ly_out is not None:
with open(ly_out, 'w') as outfile:
outfile.write(ly_stream.encode('utf-8'))
try: # python 2
outfile.write(ly_stream.encode('utf-8'))
except TypeError: # python 3
outfile.write(ly_stream)

return ly_stream, mapping
Loading