def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track.get('title', '') parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] artist_credits = track.get('artist-credit', []) b = artist_credit_from_node(artist_credits)[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track: b = track['length'] score = self.length_score(a, b) parts.append((score, weights["length"])) releases = [] if "releases" in track: releases = track['releases'] search_score = get_score(track) if not releases: sim = linear_combination_of_weights(parts) * search_score return SimMatchTrack(similarity=sim, releasegroup=None, release=None, track=track) if 'isvideo' in weights: metadata_is_video = self['~video'] == '1' track_is_video = track.get('video', False) score = 1 if metadata_is_video == track_is_video else 0 parts.append((score, weights['isvideo'])) result = SimMatchTrack(similarity=-1, releasegroup=None, release=None, track=None) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) * search_score if sim > result.similarity: rg = release[ 'release-group'] if "release-group" in release else None result = SimMatchTrack(similarity=sim, releasegroup=rg, release=release, track=track) return result
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track.get('title', '') parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] artist_credits = track.get('artist-credit', []) b = artist_credit_from_node(artist_credits)[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track: b = track['length'] score = self.length_score(a, b) parts.append((score, weights["length"])) releases = [] if "releases" in track: releases = track['releases'] if not releases: sim = linear_combination_of_weights(parts) if 'score' in track: sim *= track['score'] / 100 return SimMatchTrack(similarity=sim, releasegroup=None, release=None, track=track) result = SimMatchTrack(similarity=-1, releasegroup=None, release=None, track=None) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if 'score' in track: sim *= track['score'] / 100 if sim > result.similarity: rg = release[ 'release-group'] if "release-group" in release else None result = SimMatchTrack(similarity=sim, releasegroup=rg, release=release, track=track) return result
def compare(self, other): parts = [] if self.length and other.length: score = self.length_score(self.length, other.length) parts.append((score, 8)) for name, weight in self.__weights: a = self[name] b = other[name] if a and b: if name in ('tracknumber', 'totaltracks'): try: ia = int(a) ib = int(b) except ValueError: ia = a ib = b score = 1.0 - (int(ia != ib)) else: score = similarity2(a, b) parts.append((score, weight)) elif (a and name in other.deleted_tags or b and name in self.deleted_tags): parts.append((0, weight)) return linear_combination_of_weights(parts)
def compare_to_release(self, release, weights): """ Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ parts = self.compare_to_release_parts(release, weights) return (linear_combination_of_weights(parts), release)
def compare_to_release(self, release, weights): """ Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ parts = self.compare_to_release_parts(release, weights) return (linear_combination_of_weights(parts), release)
def compare(self, other): parts = [] if self.length and other.length: score = self.length_score(self.length, other.length) parts.append((score, 8)) for name, weight in self.__weights: a = self[name] b = other[name] if a and b: if name in ('tracknumber', 'totaltracks'): try: ia = int(a) ib = int(b) except ValueError: ia = a ib = b score = 1.0 - (int(ia != ib)) else: score = similarity2(a, b) parts.append((score, weight)) elif (a and name in other.deleted_tags or b and name in self.deleted_tags): parts.append((0, weight)) return linear_combination_of_weights(parts)
def compare(self, other, ignored=None): parts = [] if ignored is None: ignored = [] if self.length and other.length and '~length' not in ignored: score = self.length_score(self.length, other.length) parts.append((score, 8)) for name, weight in self.__weights: if name in ignored: continue a = self[name] b = other[name] if a and b: if name in {'tracknumber', 'totaltracks', 'discnumber', 'totaldiscs'}: try: ia = int(a) ib = int(b) except ValueError: ia = a ib = b score = 1.0 - (int(ia != ib)) else: score = similarity2(a, b) parts.append((score, weight)) elif (a and name in other.deleted_tags or b and name in self.deleted_tags): parts.append((0, weight)) return linear_combination_of_weights(parts)
def compare_to_release(self, release, weights): """ Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts) * get_score(release) return SimMatchRelease(similarity=sim, release=release)
def compare_to_release(self, release, weights): """ Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts) if 'score' in release: sim *= release['score'] / 100 return (sim, release)
def compare_to_release(self, release, weights): """ Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts) if 'score' in release: sim *= release['score'] / 100 return SimMatchRelease(similarity=sim, release=release)
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track.title[0].text parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] b = artist_credit_from_node(track.artist_credit[0])[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track.children: b = int(track.length[0].text) score = 1.0 - min(abs(a - b), 30000) / 30000.0 parts.append((score, weights["length"])) releases = [] if "release_list" in track.children and "release" in track.release_list[ 0].children: releases = track.release_list[0].release if not releases: sim = linear_combination_of_weights(parts) return (sim, None, None, track) result = (-1, ) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if sim > result[0]: rg = release.release_group[ 0] if "release_group" in release.children else None result = (sim, rg, release, track) return result
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track.get('title', '') parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] artist_credits = track.get('artist-credit', []) b = artist_credit_from_node(artist_credits)[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track: b = track['length'] score = self.length_score(a, b) parts.append((score, weights["length"])) releases = [] if "releases" in track: releases = track['releases'] if not releases: sim = linear_combination_of_weights(parts) return SimMatchTrack(similarity=sim, releasegroup=None, release=None, track=track) result = SimMatchTrack(similarity=-1, releasegroup=None, release=None, track=None) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if 'score' in track: sim *= track['score'] / 100 if sim > result.similarity: rg = release['release-group'] if "release-group" in release else None result = SimMatchTrack(similarity=sim, releasegroup=rg, release=release, track=track) return result
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track['title'] parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] b = artist_credit_from_node(track['artist-credit'])[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track: b = track['length'] score = self.length_score(a, b) parts.append((score, weights["length"])) releases = [] if "releases" in track: releases = track['releases'] if not releases: sim = linear_combination_of_weights(parts) return (sim, None, None, track) result = (-1, ) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if sim > result[0]: rg = release[ 'release-group'] if "release-group" in release else None result = (sim, rg, release, track) return result
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track.title[0].text parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] b = artist_credit_from_node(track.artist_credit[0])[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track.children: b = int(track.length[0].text) score = 1.0 - min(abs(a - b), 30000) / 30000.0 parts.append((score, weights["length"])) releases = [] if "release_list" in track.children and "release" in track.release_list[0].children: releases = track.release_list[0].release if not releases: sim = linear_combination_of_weights(parts) return (sim, None, None, track) result = (-1,) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if sim > result[0]: rg = release.release_group[0] if "release_group" in release.children else None result = (sim, rg, release, track) return result
def compare_to_track(self, track, weights): parts = [] if 'title' in self: a = self['title'] b = track['title'] parts.append((similarity2(a, b), weights["title"])) if 'artist' in self: a = self['artist'] b = artist_credit_from_node(track['artist-credit'])[0] parts.append((similarity2(a, b), weights["artist"])) a = self.length if a > 0 and 'length' in track: b = track['length'] score = 1.0 - min(abs(a - b), 30000) / 30000.0 parts.append((score, weights["length"])) releases = [] if "releases" in track: releases = track['releases'] if not releases: sim = linear_combination_of_weights(parts) return (sim, None, None, track) result = (-1,) for release in releases: release_parts = self.compare_to_release_parts(release, weights) sim = linear_combination_of_weights(parts + release_parts) if sim > result[0]: rg = release['release-group'] if "release-group" in release else None result = (sim, rg, release, track) return result
def _translate_artist_node(node): config = get_config() transl, translsort = None, None if config.setting['translate_artist_names']: locale = config.setting["artist_locale"] lang = locale.split("_")[0] if "aliases" in node: result = (-1, (None, None)) for alias in node['aliases']: if not alias["primary"]: continue if "locale" not in alias: continue parts = [] if alias['locale'] == locale: score = 0.8 elif alias['locale'] == lang: score = 0.6 elif alias['locale'].split("_")[0] == lang: score = 0.4 else: continue parts.append((score, 5)) if alias["type"] == "Artist name": score = 0.8 elif alias["type"] == "Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 parts.append((score, 5)) comb = linear_combination_of_weights(parts) if comb > result[0]: result = (comb, (alias['name'], alias["sort-name"])) transl, translsort = result[1] if not transl: translsort = node['sort-name'] transl = translate_from_sortname(node['name'] or "", translsort) else: transl, translsort = node['name'], node['sort-name'] return (transl, translsort)
def _translate_artist_node(node): transl, translsort = None, None if config.setting['translate_artist_names']: locale = config.setting["artist_locale"] lang = locale.split("_")[0] if "alias_list" in node.children: result = (-1, (None, None)) for alias in node.alias_list[0].alias: if alias.attribs.get("primary") != "primary": continue if "locale" not in alias.attribs: continue parts = [] if alias.locale == locale: score = 0.8 elif alias.locale == lang: score = 0.6 elif alias.locale.split("_")[0] == lang: score = 0.4 else: continue parts.append((score, 5)) if alias.attribs.get("type") == "Artist name": score = 0.8 elif alias.attribs.get("type") == "Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 parts.append((score, 5)) comb = linear_combination_of_weights(parts) if comb > result[0]: result = (comb, (alias.text, alias.attribs["sort_name"])) transl, translsort = result[1] if not transl: translsort = node.sort_name[0].text transl = translate_from_sortname(node.name[0].text, translsort) else: transl, translsort = node.name[0].text, node.sort_name[0].text return (transl, translsort)
def _translate_artist_node(node): transl, translsort = None, None if config.setting['translate_artist_names']: locale = config.setting["artist_locale"] lang = locale.split("_")[0] if "alias_list" in node.children: result = (-1, (None, None)) for alias in node.alias_list[0].alias: if alias.attribs.get("primary") != "primary": continue if "locale" not in alias.attribs: continue parts = [] if alias.locale == locale: score = 0.8 elif alias.locale == lang: score = 0.6 elif alias.locale.split("_")[0] == lang: score = 0.4 else: continue parts.append((score, 5)) if alias.attribs.get("type") == u"Artist name": score = 0.8 elif alias.attribs.get("type") == u"Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 parts.append((score, 5)) comb = linear_combination_of_weights(parts) if comb > result[0]: result = (comb, (alias.text, alias.attribs["sort_name"])) transl, translsort = result[1] if not transl: translsort = node.sort_name[0].text transl = translate_from_sortname(node.name[0].text, translsort) else: transl, translsort = node.name[0].text, node.sort_name[0].text return (transl, translsort)
def _translate_artist_node(node): transl, translsort = None, None if config.setting['translate_artist_names']: locale = config.setting["artist_locale"] lang = locale.split("_")[0] if "aliases" in node: result = (-1, (None, None)) for alias in node['aliases']: if not alias["primary"]: continue if "locale" not in alias: continue parts = [] if alias['locale'] == locale: score = 0.8 elif alias['locale'] == lang: score = 0.6 elif alias['locale'].split("_")[0] == lang: score = 0.4 else: continue parts.append((score, 5)) if alias["type"] == "Artist name": score = 0.8 elif alias["type"] == "Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 parts.append((score, 5)) comb = linear_combination_of_weights(parts) if comb > result[0]: result = (comb, (alias['name'], alias["sort-name"])) transl, translsort = result[1] if not transl: translsort = node['sort-name'] transl = translate_from_sortname(node['name'] or "", translsort) else: transl, translsort = node['name'], node['sort-name'] return (transl, translsort)
def compare(self, other): parts = [] if self.length and other.length: score = 1.0 - min(abs(self.length - other.length), 30000) / 30000.0 parts.append((score, 8)) for name, weight in self.__weights: a = self[name] b = other[name] if a and b: if name in ('tracknumber', 'totaltracks'): try: ia = int(a) ib = int(b) except ValueError: ia = a ib = b score = 1.0 - abs(cmp(ia, ib)) else: score = similarity2(a, b) parts.append((score, weight)) return linear_combination_of_weights(parts)
def test_5(self): parts = [(0.95, 100), (0.05, 399), (0.0, 1), (1.0, 0)] self.assertEqual(util.linear_combination_of_weights(parts), 0.2299)
def test_4(self): parts = [(0.5, 4), (1.0, 1)] self.assertEqual(util.linear_combination_of_weights(parts), 0.6)
def test_2(self): parts = [(0.0, 1), (0.0, 0), (1.0, 0)] self.assertEqual(util.linear_combination_of_weights(parts), 0.0)
def test_0(self): parts = [] self.assertEqual(util.linear_combination_of_weights(parts), 0.0)
def _translate_artist_node(node): config = get_config() transl, translsort = None, None if config.setting['translate_artist_names']: if config.setting['translate_artist_names_script_exception']: log_text = 'Script alpha characters found in "{0}": '.format( node["name"], ) detected_scripts = detect_script_weighted(node["name"]) if detected_scripts: log_text += "; ".join( list("{0} ({1:.1f}%)".format( scr_id, detected_scripts[scr_id] * 100) for scr_id in detected_scripts)) else: log_text += "None" log.debug(log_text) if detected_scripts: if config.setting["script_exceptions"]: log_text = " found in selected scripts: " + "; ".join( list("{0} ({1}%)".format(scr[0], scr[1]) for scr in config.setting["script_exceptions"])) for script_id, script_weighting in config.setting[ "script_exceptions"]: if script_id in detected_scripts and detected_scripts[ script_id] >= script_weighting / 100: log.debug("Match" + log_text) return node['name'], node['sort-name'] log.debug("No match" + log_text) else: log.warning( "No scripts selected for translation exception match check." ) def check_higher_score(locale_dict, locale, score): return locale not in locale_dict or score > locale_dict[locale][0] # Prepare dictionaries of available locale aliases full_locales = {} root_locales = {} if "aliases" in node: for alias in node['aliases']: if not alias["primary"]: continue if "locale" not in alias: continue full_locale = alias['locale'] root_locale = full_locale.split("_")[0] full_parts = [] root_parts = [] score = 0.8 full_parts.append((score, 5)) if '_' in full_locale: score = 0.4 root_parts.append((score, 5)) if alias["type"] == "Artist name": score = 0.8 elif alias["type"] == "Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 full_parts.append((score, 5)) root_parts.append((score, 5)) comb = linear_combination_of_weights(full_parts) if check_higher_score(full_locales, full_locale, comb): full_locales[full_locale] = (comb, (alias['name'], alias["sort-name"])) comb = linear_combination_of_weights(root_parts) if check_higher_score(root_locales, root_locale, comb): root_locales[root_locale] = (comb, (alias['name'], alias["sort-name"])) # First pass to match full locale if available for locale in config.setting["artist_locales"]: if locale in full_locales: return full_locales[locale][1] # Second pass to match root locale if available for locale in config.setting["artist_locales"]: lang = locale.split("_")[0] if lang in root_locales: return root_locales[lang][1] # No matches found in available alias locales translsort = node['sort-name'] transl = translate_from_sortname(node['name'] or "", translsort) else: transl, translsort = node['name'], node['sort-name'] return (transl, translsort)
def _translate_artist_node(node): config = get_config() transl, translsort = None, None if config.setting['translate_artist_names']: if config.setting['translate_artist_names_script_exception']: threshhold = config.setting["artist_script_exception_weighting"] / 100 detected_scripts = list_script_weighted(node["name"], threshhold) for script_id in config.setting["artist_script_exceptions"]: if script_id in detected_scripts: return node['name'], node['sort-name'] def check_higher_score(locale_dict, locale, score): return locale not in locale_dict or score > locale_dict[locale][0] # Prepare dictionaries of available locale aliases full_locales = {} root_locales = {} if "aliases" in node: for alias in node['aliases']: if not alias["primary"]: continue if "locale" not in alias: continue full_locale = alias['locale'] root_locale = full_locale.split("_")[0] full_parts = [] root_parts = [] score = 0.8 full_parts.append((score, 5)) if '_' in full_locale: score = 0.4 root_parts.append((score, 5)) if alias["type"] == "Artist name": score = 0.8 elif alias["type"] == "Legal Name": score = 0.5 else: # as 2014/09/19, only Artist or Legal names should have the # Primary flag score = 0.0 full_parts.append((score, 5)) root_parts.append((score, 5)) comb = linear_combination_of_weights(full_parts) if check_higher_score(full_locales, full_locale, comb): full_locales[full_locale] = (comb, (alias['name'], alias["sort-name"])) comb = linear_combination_of_weights(root_parts) if check_higher_score(root_locales, root_locale, comb): root_locales[root_locale] = (comb, (alias['name'], alias["sort-name"])) # First pass to match full locale if available for locale in config.setting["artist_locales"]: if locale in full_locales: return full_locales[locale][1] # Second pass to match root locale if available for locale in config.setting["artist_locales"]: lang = locale.split("_")[0] if lang in root_locales: return root_locales[lang][1] # No matches found in available alias locales translsort = node['sort-name'] transl = translate_from_sortname(node['name'] or "", translsort) else: transl, translsort = node['name'], node['sort-name'] return (transl, translsort)
def test_0(self): parts = [] self.assertEqual(util.linear_combination_of_weights(parts), 0.0)
def test_5(self): parts = [(0.95, 100), (0.05, 399), (0.0, 1), (1.0, 0)] self.assertEqual(util.linear_combination_of_weights(parts), 0.2299)
def test_4(self): parts = [(0.5, 4), (1.0, 1)] self.assertEqual(util.linear_combination_of_weights(parts), 0.6)
def test_2(self): parts = [(0.0, 1), (0.0, 0), (1.0, 0)] self.assertEqual(util.linear_combination_of_weights(parts), 0.0)