mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-22 02:08:12 +08:00
Add caching back in (#312)
* Add caching back in Works now against filter instead of dataframe view * Layout cache and move post->put * Fix tests
This commit is contained in:
+1
-1
@@ -461,7 +461,7 @@ Get the _default_ layout for all observations or (_future_) all variables. Retur
|
||||
}
|
||||
```
|
||||
|
||||
### POST /layout/obs, (_future_) POST /layout/var
|
||||
### PUT /layout/obs, (_future_) PUT /layout/var
|
||||
|
||||
Generate layout for the caller-specified subset of data, as indicated by the filter. This operation implicitly requests a re-layout operation to be performed on the specified data.
|
||||
|
||||
|
||||
@@ -670,17 +670,12 @@ class LayoutObsAPI(Resource):
|
||||
},
|
||||
}
|
||||
})
|
||||
def post(self):
|
||||
def put(self):
|
||||
try:
|
||||
return make_response(
|
||||
jsonify({
|
||||
"layout": current_app.data.layout(
|
||||
request.get_json()["filter"],
|
||||
interactive_limit=current_app.data.features["layout"]["obs"]["interactiveLimit"]
|
||||
)
|
||||
}),
|
||||
HTTPStatus.OK
|
||||
)
|
||||
filter = request.get_json()["filter"]
|
||||
interactive_limit = current_app.data.features["layout"]["obs"]["interactiveLimit"]
|
||||
layout = current_app.data.layout(filter, interactive_limit=interactive_limit)
|
||||
return make_response(jsonify({"layout": layout}), HTTPStatus.OK)
|
||||
except FilterError as e:
|
||||
return make_response(e.message, HTTPStatus.BAD_REQUEST)
|
||||
except InteractiveError:
|
||||
|
||||
@@ -6,8 +6,7 @@ from pandas import DataFrame, Series
|
||||
import scanpy.api as sc
|
||||
from scipy import stats
|
||||
|
||||
# TODO fix memoization so that it correctly identifies the same request
|
||||
# from server.app.app import cache
|
||||
from server.app.app import cache
|
||||
from server.app.driver.driver import CXGDriver
|
||||
from server.app.util.constants import Axis, DEFAULT_TOP_N, DiffExpMode
|
||||
from server.app.util.utils import FilterError, InteractiveError
|
||||
@@ -201,7 +200,7 @@ class ScanpyEngine(CXGDriver):
|
||||
index = np.logical_and(index, key_idx)
|
||||
return index
|
||||
|
||||
# @cache.memoize()
|
||||
@cache.memoize()
|
||||
def annotation(self, filter, axis, fields=None):
|
||||
"""
|
||||
Gets annotation value for each observation
|
||||
@@ -224,7 +223,7 @@ class ScanpyEngine(CXGDriver):
|
||||
"data": annotations.reset_index().values.tolist()
|
||||
}
|
||||
|
||||
# @cache.memoize()
|
||||
@cache.memoize()
|
||||
def data_frame(self, filter, axis):
|
||||
"""
|
||||
Retrieves data for each variable for observations in data frame
|
||||
@@ -261,7 +260,6 @@ class ScanpyEngine(CXGDriver):
|
||||
}
|
||||
return result
|
||||
|
||||
# @cache.memoize()
|
||||
def diffexp(self, filter1, filter2, top_n=None, interactive_limit=None):
|
||||
"""
|
||||
Computes the top differentially expressed variables between two observation sets. If dataframes
|
||||
@@ -321,7 +319,7 @@ class ScanpyEngine(CXGDriver):
|
||||
# Results need to be returned in var index order
|
||||
return sorted(result, key=lambda gene: gene[0])
|
||||
|
||||
# @cache.memoize()
|
||||
@cache.memoize()
|
||||
def layout(self, filter, interactive_limit=None):
|
||||
"""
|
||||
Computes a n-d layout for cells through dimensionality reduction.
|
||||
|
||||
+37
-10
@@ -84,22 +84,16 @@ class EndPoints(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
}
|
||||
result = self.session.post(url, json=obs_filter)
|
||||
result = self.session.put(url, json=obs_filter)
|
||||
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||
result_data = result.json()
|
||||
self.assertEqual(len(result_data["layout"]["coordinates"]), 15)
|
||||
|
||||
def test_bad_filter(self):
|
||||
endpoints = {
|
||||
"layout/obs": "post",
|
||||
"annotations/obs": "put",
|
||||
"annotations/var": "put",
|
||||
"data/obs": "put",
|
||||
"data/var": "put"
|
||||
}
|
||||
for endpoint, method in endpoints.items():
|
||||
endpoints = ["layout/obs", "annotations/obs", "annotations/var", "data/obs", "data/var"]
|
||||
for endpoint in endpoints:
|
||||
url = f"{URL_BASE}{endpoint}"
|
||||
result = getattr(self.session, method)(url, json=BAD_FILTER)
|
||||
result = self.session.put(url, json=BAD_FILTER)
|
||||
self.assertEqual(result.status_code, HTTPStatus.BAD_REQUEST)
|
||||
|
||||
def test_get_annotations_obs(self):
|
||||
@@ -373,6 +367,39 @@ class EndPoints(unittest.TestCase):
|
||||
self.assertEqual(len(result_data["obs"]), 2638)
|
||||
self.assertEqual(len(result_data["var"][0]), 2639)
|
||||
|
||||
def test_cache(self):
|
||||
endpoint = "annotations/var"
|
||||
url = f"{URL_BASE}{endpoint}"
|
||||
f1 = {"filter": {"var": {"annotation_value": [{"name": "name",
|
||||
"values": ["HLA-DRB1", "HLA-DQA1", "HLA-DQB1", "HLA-DPA1",
|
||||
"HLA-DPB1", "MS4A1", "IL32", "CCL5", "CD79B",
|
||||
"CD79A"]}]}}}
|
||||
result = self.session.put(url, json=f1)
|
||||
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||
result_data1 = result.json()
|
||||
f2 = {"filter": {"var": {"annotation_value": [{"name": "name",
|
||||
"values": ["FGFBP2", "GZMA", "LTB", "PRF1", "CTSW", "GZMH",
|
||||
"CCL5", "CCL4", "CST7", "NKG7"]}]}}}
|
||||
result = self.session.put(url, json=f2)
|
||||
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||
result_data2 = result.json()
|
||||
self.assertNotEqual(result_data1, result_data2)
|
||||
|
||||
def test_cache_nofilter(self):
|
||||
endpoint = "annotations/var"
|
||||
url = f"{URL_BASE}{endpoint}"
|
||||
f1 = {"filter": {}}
|
||||
result = self.session.put(url, json=f1)
|
||||
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||
result_data1 = result.json()
|
||||
f2 = {"filter": {"var": {"annotation_value": [{"name": "name",
|
||||
"values": ["FGFBP2", "GZMA", "LTB", "PRF1", "CTSW", "GZMH",
|
||||
"CCL5", "CCL4", "CST7", "NKG7"]}]}}}
|
||||
result = self.session.put(url, json=f2)
|
||||
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||
result_data2 = result.json()
|
||||
self.assertNotEqual(result_data1, result_data2)
|
||||
|
||||
def test_static(self):
|
||||
endpoint = "static"
|
||||
file = "js/service-worker.js"
|
||||
|
||||
Reference in New Issue
Block a user