Round relevance (plus refactor)
This commit is contained in:
@@ -6,13 +6,17 @@ from collections import namedtuple
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
METADATA_RELEVANCE = 'relevance'
|
|
||||||
METADATA_PRECISION = 'precision'
|
|
||||||
METADATA_MATCH_TYPES = 'match_types'
|
|
||||||
|
|
||||||
PRECISION_PRECISE = 'precise'
|
PRECISION_PRECISE = 'precise'
|
||||||
PRECISION_INTERPOLATED = 'interpolated'
|
PRECISION_INTERPOLATED = 'interpolated'
|
||||||
|
|
||||||
|
|
||||||
|
def geocoder_metadata(relevance, precision, match_types):
|
||||||
|
return {
|
||||||
|
'relevance': round(relevance, 2),
|
||||||
|
'precision': precision,
|
||||||
|
'match_types': match_types
|
||||||
|
}
|
||||||
|
|
||||||
def compose_address(street, city=None, state=None, country=None):
|
def compose_address(street, city=None, state=None, country=None):
|
||||||
return ', '.join(filter(None, [street, city, state, country]))
|
return ', '.join(filter(None, [street, city, state, country]))
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
from urlparse import parse_qs
|
from urlparse import parse_qs
|
||||||
|
|
||||||
from exceptions import MalformedResult
|
from exceptions import MalformedResult
|
||||||
from cartodb_services.geocoder import compose_address, METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
from cartodb_services.geocoder import compose_address, geocoder_metadata, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
||||||
from cartodb_services.google.exceptions import InvalidGoogleCredentials
|
from cartodb_services.google.exceptions import InvalidGoogleCredentials
|
||||||
from client_factory import GoogleMapsClientFactory
|
from client_factory import GoogleMapsClientFactory
|
||||||
|
|
||||||
@@ -82,11 +82,11 @@ class GoogleMapsGeocoder():
|
|||||||
partial_factor = PARTIAL_FACTOR if partial_match else 1
|
partial_factor = PARTIAL_FACTOR if partial_match else 1
|
||||||
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
||||||
for match_level in result['types']]
|
for match_level in result['types']]
|
||||||
return {
|
return geocoder_metadata(
|
||||||
METADATA_RELEVANCE: base_relevance * partial_factor,
|
base_relevance * partial_factor,
|
||||||
METADATA_PRECISION: PRECISION_BY_LOCATION_TYPE[location_type],
|
PRECISION_BY_LOCATION_TYPE[location_type],
|
||||||
METADATA_MATCH_TYPES: filter(None, match_types)
|
filter(None, match_types)
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
def _build_optional_parameters(self, city=None, state=None,
|
def _build_optional_parameters(self, city=None, state=None,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from collections import namedtuple
|
|||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
from cartodb_services import StreetPointBulkGeocoder
|
from cartodb_services import StreetPointBulkGeocoder
|
||||||
from cartodb_services.here import HereMapsGeocoder
|
from cartodb_services.here import HereMapsGeocoder
|
||||||
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES
|
from cartodb_services.geocoder import geocoder_metadata
|
||||||
from cartodb_services.metrics import Traceable
|
from cartodb_services.metrics import Traceable
|
||||||
from cartodb_services.tools.exceptions import ServiceException
|
from cartodb_services.tools.exceptions import ServiceException
|
||||||
|
|
||||||
@@ -138,11 +138,11 @@ class HereMapsBulkGeocoder(HereMapsGeocoder, StreetPointBulkGeocoder):
|
|||||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None)
|
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None)
|
||||||
results.append((row['recId'],
|
results.append((row['recId'],
|
||||||
[row['displayLongitude'], row['displayLatitude']],
|
[row['displayLongitude'], row['displayLatitude']],
|
||||||
{
|
geocoder_metadata(
|
||||||
METADATA_RELEVANCE: float(row['relevance']),
|
float(row['relevance']),
|
||||||
METADATA_PRECISION: precision,
|
precision,
|
||||||
METADATA_MATCH_TYPES: [match_type] if match_type else []
|
[match_type] if match_type else []
|
||||||
}))
|
)))
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import requests
|
|||||||
|
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
|
||||||
from cartodb_services.metrics import Traceable
|
from cartodb_services.metrics import Traceable
|
||||||
|
|
||||||
class HereMapsGeocoder(Traceable):
|
class HereMapsGeocoder(Traceable):
|
||||||
@@ -146,8 +146,8 @@ class HereMapsGeocoder(Traceable):
|
|||||||
precision = self.PRECISION_BY_MATCH_TYPE[
|
precision = self.PRECISION_BY_MATCH_TYPE[
|
||||||
result.get('MatchType', 'pointAddress')]
|
result.get('MatchType', 'pointAddress')]
|
||||||
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None)
|
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None)
|
||||||
return {
|
return geocoder_metadata(
|
||||||
METADATA_RELEVANCE: result['Relevance'],
|
result['Relevance'],
|
||||||
METADATA_PRECISION: precision,
|
precision,
|
||||||
METADATA_MATCH_TYPES: [match_type] if match_type else []
|
[match_type] if match_type else []
|
||||||
}
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Python client for the Mapbox Geocoder service.
|
|||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
from mapbox import Geocoder
|
from mapbox import Geocoder
|
||||||
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
|
||||||
from cartodb_services.metrics import Traceable
|
from cartodb_services.metrics import Traceable
|
||||||
from cartodb_services.tools.exceptions import ServiceException
|
from cartodb_services.tools.exceptions import ServiceException
|
||||||
from cartodb_services.tools.qps import qps_retry
|
from cartodb_services.tools.qps import qps_retry
|
||||||
@@ -92,11 +92,11 @@ class MapboxGeocoder(Traceable):
|
|||||||
|
|
||||||
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
|
||||||
for match_level in result['place_type']]
|
for match_level in result['place_type']]
|
||||||
return {
|
return geocoder_metadata(
|
||||||
METADATA_RELEVANCE: self._normalize_relevance(float(result['relevance'])),
|
self._normalize_relevance(float(result['relevance'])),
|
||||||
METADATA_PRECISION: precision,
|
precision,
|
||||||
METADATA_MATCH_TYPES: filter(None, match_types)
|
filter(None, match_types)
|
||||||
}
|
)
|
||||||
|
|
||||||
def _normalize_relevance(self, relevance):
|
def _normalize_relevance(self, relevance):
|
||||||
return 1 if relevance >= 0.99 else relevance
|
return 1 if relevance >= 0.99 else relevance
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import json
|
|||||||
import requests
|
import requests
|
||||||
from uritemplate import URITemplate
|
from uritemplate import URITemplate
|
||||||
from math import tanh
|
from math import tanh
|
||||||
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED
|
from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
|
||||||
from cartodb_services.metrics import Traceable
|
from cartodb_services.metrics import Traceable
|
||||||
from cartodb_services.tools.exceptions import ServiceException
|
from cartodb_services.tools.exceptions import ServiceException
|
||||||
from cartodb_services.tools.qps import qps_retry
|
from cartodb_services.tools.qps import qps_retry
|
||||||
@@ -144,11 +144,11 @@ class TomTomGeocoder(Traceable):
|
|||||||
def _extract_metadata_from_result(self, result):
|
def _extract_metadata_from_result(self, result):
|
||||||
score = self._normalize_score(result['score'])
|
score = self._normalize_score(result['score'])
|
||||||
match_type = MATCH_TYPE_BY_MATCH_LEVEL.get(result['type'], None)
|
match_type = MATCH_TYPE_BY_MATCH_LEVEL.get(result['type'], None)
|
||||||
return {
|
return geocoder_metadata(
|
||||||
METADATA_RELEVANCE: score,
|
score,
|
||||||
METADATA_PRECISION: self._precision_from_score(score),
|
self._precision_from_score(score),
|
||||||
METADATA_MATCH_TYPES: [match_type] if match_type else []
|
[match_type] if match_type else []
|
||||||
}
|
)
|
||||||
|
|
||||||
def _normalize_score(self, score):
|
def _normalize_score(self, score):
|
||||||
return tanh(score * SCORE_NORMALIZATION_FACTOR)
|
return tanh(score * SCORE_NORMALIZATION_FACTOR)
|
||||||
|
|||||||
@@ -87,14 +87,14 @@ class TestStreetFunctionsSetUp(TestCase):
|
|||||||
'Plaza España, Barcelona':
|
'Plaza España, Barcelona':
|
||||||
{'relevance': 0.85, 'precision': 'precise', 'match_types': ['street']},
|
{'relevance': 0.85, 'precision': 'precise', 'match_types': ['street']},
|
||||||
'Santiago Rusiñol 123, Valladolid':
|
'Santiago Rusiñol 123, Valladolid':
|
||||||
{'relevance': 0.448283494533, 'precision': 'interpolated', 'match_types': ['street']}
|
{'relevance': 0.45, 'precision': 'interpolated', 'match_types': ['street']}
|
||||||
}
|
}
|
||||||
|
|
||||||
MAPBOX_METADATAS = {
|
MAPBOX_METADATAS = {
|
||||||
'Plaza España, Barcelona':
|
'Plaza España, Barcelona':
|
||||||
{'relevance': 0.666, 'precision': 'precise', 'match_types': ['point_of_interest']},
|
{'relevance': 0.67, 'precision': 'precise', 'match_types': ['point_of_interest']},
|
||||||
'Santiago Rusiñol 123, Valladolid':
|
'Santiago Rusiñol 123, Valladolid':
|
||||||
{'relevance': 0.666, 'precision': 'precise', 'match_types': ['point_of_interest']} # TODO: wrong
|
{'relevance': 0.67, 'precision': 'precise', 'match_types': ['point_of_interest']} # TODO: wrong
|
||||||
}
|
}
|
||||||
|
|
||||||
METADATAS = {
|
METADATAS = {
|
||||||
@@ -410,7 +410,7 @@ class TestBulkStreetFunctions(TestStreetFunctionsSetUp):
|
|||||||
def assert_metadata(metadata, expected):
|
def assert_metadata(metadata, expected):
|
||||||
relevance = metadata['relevance']
|
relevance = metadata['relevance']
|
||||||
expected_relevance = expected['relevance']
|
expected_relevance = expected['relevance']
|
||||||
assert_true(isclose(relevance, expected_relevance, 0.05),
|
assert_true(isclose(relevance, expected_relevance, 0.02),
|
||||||
'{} not close to {}'.format(relevance, expected_relevance))
|
'{} not close to {}'.format(relevance, expected_relevance))
|
||||||
|
|
||||||
assert_equal(metadata['precision'], expected['precision'])
|
assert_equal(metadata['precision'], expected['precision'])
|
||||||
|
|||||||
Reference in New Issue
Block a user