From a3d4d85412bdfbd87205cdfd782978ac4c99cc2c Mon Sep 17 00:00:00 2001 From: Madison May Date: Wed, 24 Sep 2014 19:51:31 -0400 Subject: [PATCH 1/3] Add local api support, fix test case --- indicoio/__init__.py | 12 +++++++++++- indicoio/images/features.py | 8 ++++---- indicoio/images/fer.py | 4 ++-- indicoio/local/__init__.py | 20 ++++++++++++++++++++ indicoio/text/lang.py | 4 ++-- indicoio/text/sentiment.py | 8 ++++---- indicoio/utils/config.py | 2 ++ tests/test_run.py | 3 +-- 8 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 indicoio/local/__init__.py create mode 100644 indicoio/utils/config.py diff --git a/indicoio/__init__.py b/indicoio/__init__.py index 098a4a9..af8394d 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -1,3 +1,6 @@ +from functools import partial +from utils import config + JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} Version, version, __version__, VERSION = ('0.4.4',) * 4 @@ -7,4 +10,11 @@ from text.sentiment import posneg as sentiment from text.lang import language from images.fer import fer from images.features import facial_features -from images.features import image_features \ No newline at end of file +from images.features import image_features + +political = partial(political, config.api_root) +sentiment = partial(sentiment, config.api_root) +language = partial(language, config.api_root) +fer = partial(fer, config.api_root) +facial_features = partial(facial_features, config.api_root) +image_features = partial(image_features, config.api_root) diff --git a/indicoio/images/features.py b/indicoio/images/features.py index d6b049b..cd56087 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -6,7 +6,7 @@ import numpy as np from indicoio import JSON_HEADERS from indicoio.utils import image_preprocess -def facial_features(image): +def facial_features(api_root, image): """ Given an grayscale input image of a face, returns a 48 dimensional feature vector explaining that face. Useful as a form of feature engineering for face oriented tasks. @@ -30,14 +30,14 @@ def facial_features(image): """ data_dict = json.dumps({"face": image}) - response = requests.post("http://api.indico.io/facialfeatures", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "facialfeatures", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'response' not in response_dict: raise ValueError(response_dict.values()[0]) else: return response_dict['response'] -def image_features(image): +def image_features(api_root, image): """ Given an input image, returns a 2048 dimensional sparse feature vector explaining that image. Useful as a form of feature engineering for image oriented tasks. @@ -69,7 +69,7 @@ def image_features(image): """ image = image_preprocess(image) data_dict = json.dumps({"image": image}) - response = requests.post("http://api.indico.io/imagefeatures", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "imagefeatures", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'Features' not in response_dict: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/images/fer.py b/indicoio/images/fer.py index f66e063..27f8162 100644 --- a/indicoio/images/fer.py +++ b/indicoio/images/fer.py @@ -4,7 +4,7 @@ import requests import numpy as np from indicoio import JSON_HEADERS -def fer(image): +def fer(api_root, image): """ Given a grayscale input image of a face, returns a probability distribution over emotional state. Input should be in a list of list format, resizing will be attempted internally but for best @@ -29,7 +29,7 @@ def fer(image): """ data_dict = json.dumps({"face": image}) - response = requests.post("http://api.indico.io/fer", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "fer", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/local/__init__.py b/indicoio/local/__init__.py new file mode 100644 index 0000000..37f0893 --- /dev/null +++ b/indicoio/local/__init__.py @@ -0,0 +1,20 @@ +from functools import partial +from indicoio.utils import config + +JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} + +Version, version, __version__, VERSION = ('0.4.3',) * 4 + +from indicoio.text.sentiment import political, posneg +from indicoio.text.sentiment import posneg as sentiment +from indicoio.text.lang import language +from indicoio.images.fer import fer +from indicoio.images.features import facial_features +from indicoio.images.features import image_features + +political = partial(political, config.local_api_root) +sentiment = partial(sentiment, config.local_api_root) +language = partial(language, config.local_api_root) +fer = partial(fer, config.local_api_root) +facial_features = partial(facial_features, config.local_api_root) +image_features = partial(image_features, config.local_api_root) diff --git a/indicoio/text/lang.py b/indicoio/text/lang.py index d4b6767..665522d 100644 --- a/indicoio/text/lang.py +++ b/indicoio/text/lang.py @@ -3,7 +3,7 @@ import json from indicoio import JSON_HEADERS -def language(text): +def language(api_root, text): """ Given input text, returns a probability distribution over 33 possible languages of what language the text was written in. @@ -27,7 +27,7 @@ def language(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/language", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "language", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/text/sentiment.py b/indicoio/text/sentiment.py index ba5e8fe..b570f5f 100644 --- a/indicoio/text/sentiment.py +++ b/indicoio/text/sentiment.py @@ -4,7 +4,7 @@ import json from indicoio import JSON_HEADERS from indicoio.utils import normalize -def political(text): +def political(api_root, text): """ Given input text, returns a probability distribution over the political alignment of the speaker. @@ -31,14 +31,14 @@ def political(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/political", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "political", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) else: return response_dict -def posneg(text): +def posneg(api_root, text): """ Given input text, returns a scalar estimate of the sentiment of that text. Values are roughly in the range 0 to 1 with 0.5 indicating neutral sentiment. @@ -60,7 +60,7 @@ def posneg(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/sentiment", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "sentiment", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'Sentiment' not in response_dict: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/utils/config.py b/indicoio/utils/config.py new file mode 100644 index 0000000..5e516d9 --- /dev/null +++ b/indicoio/utils/config.py @@ -0,0 +1,2 @@ +local_api_root = "http://localhost:9438/" +api_root = "http://www.indico.io/api/" \ No newline at end of file diff --git a/tests/test_run.py b/tests/test_run.py index d2a3bad..d5169cb 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -20,8 +20,7 @@ class FullAPIRun(unittest.TestCase): test_string = "Worst song ever." response = sentiment(test_string) - self.assertTrue(isinstance(response, dict)) - self.assertEqual(posneg_set, set(response.keys())) + self.assertTrue(isinstance(response, float)) def test_good_fer(self): fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy']) From 1d499307646b23b13e02061b065044398b9db341 Mon Sep 17 00:00:00 2001 From: Madison May Date: Wed, 24 Sep 2014 19:53:23 -0400 Subject: [PATCH 2/3] Add local tests --- indicoio/__init__.py | 3 +- indicoio/local/__init__.py | 3 +- indicoio/utils/config.py | 2 +- tests/test_local.py | 90 +++++++++++++++++++++++++++ tests/{test_run.py => test_remote.py} | 0 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 tests/test_local.py rename tests/{test_run.py => test_remote.py} (100%) diff --git a/indicoio/__init__.py b/indicoio/__init__.py index af8394d..29c3cb3 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -3,7 +3,7 @@ from utils import config JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} -Version, version, __version__, VERSION = ('0.4.4',) * 4 +Version, version, __version__, VERSION = ('0.4.5',) * 4 from text.sentiment import political, posneg from text.sentiment import posneg as sentiment @@ -14,6 +14,7 @@ from images.features import image_features political = partial(political, config.api_root) sentiment = partial(sentiment, config.api_root) +posneg = partial(sentiment, config.api_root) language = partial(language, config.api_root) fer = partial(fer, config.api_root) facial_features = partial(facial_features, config.api_root) diff --git a/indicoio/local/__init__.py b/indicoio/local/__init__.py index 37f0893..625109d 100644 --- a/indicoio/local/__init__.py +++ b/indicoio/local/__init__.py @@ -3,8 +3,6 @@ from indicoio.utils import config JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} -Version, version, __version__, VERSION = ('0.4.3',) * 4 - from indicoio.text.sentiment import political, posneg from indicoio.text.sentiment import posneg as sentiment from indicoio.text.lang import language @@ -14,6 +12,7 @@ from indicoio.images.features import image_features political = partial(political, config.local_api_root) sentiment = partial(sentiment, config.local_api_root) +posneg = partial(sentiment, config.local_api_root) language = partial(language, config.local_api_root) fer = partial(fer, config.local_api_root) facial_features = partial(facial_features, config.local_api_root) diff --git a/indicoio/utils/config.py b/indicoio/utils/config.py index 5e516d9..f6b622e 100644 --- a/indicoio/utils/config.py +++ b/indicoio/utils/config.py @@ -1,2 +1,2 @@ local_api_root = "http://localhost:9438/" -api_root = "http://www.indico.io/api/" \ No newline at end of file +api_root = "http://api.indico.io/" \ No newline at end of file diff --git a/tests/test_local.py b/tests/test_local.py new file mode 100644 index 0000000..241d7da --- /dev/null +++ b/tests/test_local.py @@ -0,0 +1,90 @@ +import unittest + +import numpy as np + +from indicoio.local import political, sentiment, fer, facial_features, language + + +class FullAPIRun(unittest.TestCase): + + def test_political(self): + political_set = set(['Libertarian', 'Liberal', 'Conservative', 'Green']) + test_string = "Guns don't kill people, people kill people." + response = political(test_string) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(political_set, set(response.keys())) + + def test_posneg(self): + posneg_set = set(['Sentiment']) + test_string = "Worst song ever." + response = sentiment(test_string) + + self.assertTrue(isinstance(response, float)) + + def test_good_fer(self): + fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy']) + test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() + response = fer(test_face) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(fer_set, set(response.keys())) + + def test_bad_fer(self): + fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy']) + test_face = np.linspace(0,50,56*56).reshape(56,56).tolist() + response = fer(test_face) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(fer_set, set(response.keys())) + + def test_good_facial_features(self): + test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() + response = facial_features(test_face) + + self.assertTrue(isinstance(response, list)) + self.assertEqual(len(response), 48) + + def test_language(self): + language_set = set([ + 'English', + 'Spanish', + 'Tagalog', + 'Esperanto', + 'French', + 'Chinese', + 'French', + 'Bulgarian', + 'Latin', + 'Slovak', + 'Hebrew', + 'Russian', + 'German', + 'Japanese', + 'Korean', + 'Portuguese', + 'Italian', + 'Polish', + 'Turkish', + 'Dutch', + 'Arabic', + 'Persian (Farsi)', + 'Czech', + 'Swedish', + 'Indonesian', + 'Vietnamese', + 'Romanian', + 'Greek', + 'Danish', + 'Hungarian', + 'Thai', + 'Finnish', + 'Norwegian', + 'Lithuanian' + ]) + language_dict = language('clearly an english sentence') + self.assertEqual(language_set, set(language_dict.keys())) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_run.py b/tests/test_remote.py similarity index 100% rename from tests/test_run.py rename to tests/test_remote.py From 892d3439f094316ab2aba5c50448c4e8636e3a60 Mon Sep 17 00:00:00 2001 From: Madison May Date: Wed, 24 Sep 2014 20:03:22 -0400 Subject: [PATCH 3/3] Support for posneg --- indicoio/__init__.py | 1 + indicoio/local/__init__.py | 1 + 2 files changed, 2 insertions(+) diff --git a/indicoio/__init__.py b/indicoio/__init__.py index 29c3cb3..0646c43 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -13,6 +13,7 @@ from images.features import facial_features from images.features import image_features political = partial(political, config.api_root) +posneg = partial(posneg, config.api_root) sentiment = partial(sentiment, config.api_root) posneg = partial(sentiment, config.api_root) language = partial(language, config.api_root) diff --git a/indicoio/local/__init__.py b/indicoio/local/__init__.py index 625109d..2d50e7f 100644 --- a/indicoio/local/__init__.py +++ b/indicoio/local/__init__.py @@ -11,6 +11,7 @@ from indicoio.images.features import facial_features from indicoio.images.features import image_features political = partial(political, config.local_api_root) +posneg = partial(posneg, config.local_api_root) sentiment = partial(sentiment, config.local_api_root) posneg = partial(sentiment, config.local_api_root) language = partial(language, config.local_api_root)