From f264e25cd21f063aaca058961245f368eaa49219 Mon Sep 17 00:00:00 2001 From: JanRiedelsheimer Date: Tue, 3 Dec 2024 15:59:35 +0100 Subject: [PATCH] added http_model in pysaliency --- http_submission/sample_evaluation.py | 66 +++------------------------- http_submission/sample_submission.py | 1 + pysaliency/http_models.py | 54 +++++++++++++++++++++++ 3 files changed, 60 insertions(+), 61 deletions(-) create mode 100644 pysaliency/http_models.py diff --git a/http_submission/sample_evaluation.py b/http_submission/sample_evaluation.py index 520b895..67ce6e4 100644 --- a/http_submission/sample_evaluation.py +++ b/http_submission/sample_evaluation.py @@ -1,62 +1,10 @@ import numpy as np -import pickle -import requests import sys from sample_submission import MySimpleScanpathModel -from PIL import Image -from io import BytesIO -import json -import matplotlib.pyplot as plt -from pysaliency.plotting import plot_scanpath +from pysaliency.http_models import HTTPScanpathModel sys.path.insert(0, '..') import pysaliency -class HTTPScanpathModel(MySimpleScanpathModel): - def __init__(self, url): - self.url = url - - @property - def log_density_url(self): - return self.url + "/conditional_log_density" - - @property - def type_url(self): - return self.url + "/type" - - def conditional_log_density(self, stimulus, x_hist, y_hist, t_hist, attributes=None, out=None): - # build request - pil_image = Image.fromarray(stimulus) - image_bytes = BytesIO() - pil_image.save(image_bytes, format='png') - - def _convert_attribute(attribute): - if isinstance(attribute, np.ndarray): - return attribute.tolist() - return attribute - - json_data = { - "x_hist": list(x_hist), - "y_hist": list(y_hist), - "t_hist": list(t_hist), - "attributes": {key: _convert_attribute(value) for key, value in (attributes or {}).items()} - } - - # send request - response = requests.post(f"{self.log_density_url}", data={'json_data': json.dumps(json_data)}, files={'stimulus': image_bytes.getvalue()}) - - # parse response - if response.status_code != 200: - raise ValueError(f"Server returned status code {response.status_code}") - - return np.array(response.json()['log_density']) - - def check_type(self): - response = requests.get(f"{self.type_url}").json() - if not response['type'] == 'ScanpathModel': - raise ValueError(f"invalid Model type: {response['type']}. Expected 'ScanpathModel'") - if not response['version'] in ['v1.0.0']: - raise ValueError(f"invalid Model type: {response['version']}. Expected 'v1.0.0'") - if __name__ == "__main__": http_model = HTTPScanpathModel("http://localhost:4000") @@ -69,8 +17,7 @@ def check_type(self): stimuli, fixations = pysaliency.get_mit1003(location='pysaliency_datasets') eval_fixations = fixations[fixations.scanpath_history_length > 0] - server_density_list = [] - model_density_list = [] + for fixation_index in range(10): # get server response for one stimulus server_density = http_model.conditional_log_density( @@ -87,9 +34,6 @@ def check_type(self): t_hist=eval_fixations.t_hist[fixation_index] ) - server_density_list.append(server_density) - model_density_list.append(model_density) - - # Testing - test = np.testing.assert_allclose(server_density_list, model_density_list) - print(test) \ No newline at end of file + # Testing + test = np.testing.assert_allclose(server_density, model_density) + \ No newline at end of file diff --git a/http_submission/sample_submission.py b/http_submission/sample_submission.py index 92845b7..e73b8c3 100644 --- a/http_submission/sample_submission.py +++ b/http_submission/sample_submission.py @@ -44,6 +44,7 @@ def __init__(self, spatial_model_bandwidth: float=0.05, saccade_width: float=0.1 self.spatial_model_bandwidth = spatial_model_bandwidth self.saccade_width = saccade_width self.spatial_model = LocalContrastModel(spatial_model_bandwidth) + # self.spatial_model = pysaliency.UniformModel() def conditional_log_density(self, stimulus, x_hist, y_hist, t_hist, attributes=None, out=None,): diff --git a/pysaliency/http_models.py b/pysaliency/http_models.py new file mode 100644 index 0000000..5523271 --- /dev/null +++ b/pysaliency/http_models.py @@ -0,0 +1,54 @@ +from .models import ScanpathModel +from PIL import Image +from io import BytesIO +import requests +import json +import numpy as np + +class HTTPScanpathModel(ScanpathModel): + def __init__(self, url): + self.url = url + self.check_type() + + @property + def log_density_url(self): + return self.url + "/conditional_log_density" + + @property + def type_url(self): + return self.url + "/type" + + def conditional_log_density(self, stimulus, x_hist, y_hist, t_hist, attributes=None, out=None): + # build request + pil_image = Image.fromarray(stimulus) + image_bytes = BytesIO() + pil_image.save(image_bytes, format='png') + + def _convert_attribute(attribute): + if isinstance(attribute, np.ndarray): + return attribute.tolist() + return attribute + + json_data = { + "x_hist": list(x_hist), + "y_hist": list(y_hist), + "t_hist": list(t_hist), + "attributes": {key: _convert_attribute(value) for key, value in (attributes or {}).items()} + } + + # send request + response = requests.post(f"{self.log_density_url}", data={'json_data': json.dumps(json_data)}, files={'stimulus': image_bytes.getvalue()}) + + # parse response + if response.status_code != 200: + raise ValueError(f"Server returned status code {response.status_code}") + + return np.array(response.json()['log_density']) + + def check_type(self): + # TODO in constuctor aufrufen, damit direkt gecheckt wird ob type passt + response = requests.get(f"{self.type_url}").json() + if not response['type'] == 'ScanpathModel': + raise ValueError(f"invalid Model type: {response['type']}. Expected 'ScanpathModel'") + if not response['version'] in ['v1.0.0']: + raise ValueError(f"invalid Model type: {response['version']}. Expected 'v1.0.0'")