mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-08 05:48:11 +08:00
Style guide cleanup
This commit is contained in:
@@ -1,12 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from flask import Flask, url_for, g
|
from flask import Flask
|
||||||
from flask_compress import Compress
|
from flask_compress import Compress
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
from flask_restful_swagger_2 import get_swagger_blueprint
|
from flask_restful_swagger_2 import get_swagger_blueprint
|
||||||
|
|
||||||
# from werkzeug.contrib.profiler import ProfilerMiddleware
|
|
||||||
|
|
||||||
from .web import webapp
|
from .web import webapp
|
||||||
from .rest_api.rest import get_api_resources
|
from .rest_api.rest import get_api_resources
|
||||||
|
|
||||||
@@ -14,11 +12,12 @@ app = Flask(__name__)
|
|||||||
Compress(app)
|
Compress(app)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
|
|
||||||
#Config
|
# Config
|
||||||
CONFIG_FILE = os.environ.get("CXG_CONFIG_FILE", default="scanpy-test.cfg")
|
CONFIG_FILE = os.environ.get("CXG_CONFIG_FILE", default="scanpy-test.cfg")
|
||||||
CXG_DIR = os.environ.get("CXG_DIRECTORY", default="/Users/charlotteweaver/Documents/Git/cxg-v2/data/")
|
CXG_DIR = os.environ.get("CXG_DIRECTORY", default="/Users/charlotteweaver/Documents/Git/cxg-v2/data/")
|
||||||
SECRET_KEY = os.environ.get("CXG_SECRET_KEY", default="SparkleAndShine")
|
SECRET_KEY = os.environ.get("CXG_SECRET_KEY", default="SparkleAndShine")
|
||||||
ENGINE = os.environ.get("CXG_ENGINE", default="scanpy")
|
ENGINE = os.environ.get("CXG_ENGINE", default="scanpy")
|
||||||
|
TITLE = os.environ.get("DATASET_TITLE", default="PBMC 3K")
|
||||||
# TODO remove the 2 when this is prod
|
# TODO remove the 2 when this is prod
|
||||||
CXG_API_BASE = os.environ.get("CXG_API_BASE2", default="http://0.0.0.0:5005/api/")
|
CXG_API_BASE = os.environ.get("CXG_API_BASE2", default="http://0.0.0.0:5005/api/")
|
||||||
|
|
||||||
@@ -30,7 +29,8 @@ app.config.update(
|
|||||||
SECRET_KEY=SECRET_KEY,
|
SECRET_KEY=SECRET_KEY,
|
||||||
CXG_API_BASE=CXG_API_BASE,
|
CXG_API_BASE=CXG_API_BASE,
|
||||||
ENGINE=ENGINE,
|
ENGINE=ENGINE,
|
||||||
DATA=CXG_DIR
|
DATA=CXG_DIR,
|
||||||
|
DATASET_TITLE=TITLE
|
||||||
)
|
)
|
||||||
|
|
||||||
app.config['PROFILE'] = True
|
app.config['PROFILE'] = True
|
||||||
@@ -52,12 +52,13 @@ docs.append(resources.get_swagger_doc())
|
|||||||
|
|
||||||
app.register_blueprint(webapp.bp)
|
app.register_blueprint(webapp.bp)
|
||||||
app.register_blueprint(resources.blueprint)
|
app.register_blueprint(resources.blueprint)
|
||||||
app.register_blueprint(get_swagger_blueprint(docs, '/api/swagger', produces=["application/json"], title="cellxgene rest api",
|
app.register_blueprint(
|
||||||
description='An API connecting ExpressionMatrix2 clustering algorithm to cellxgene'))
|
get_swagger_blueprint(docs, '/api/swagger', produces=["application/json"], title="cellxgene rest api",
|
||||||
|
description='An API connecting ExpressionMatrix2 clustering algorithm to cellxgene'))
|
||||||
|
|
||||||
|
|
||||||
app.add_url_rule('/', endpoint='index')
|
app.add_url_rule('/', endpoint='index')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host='0.0.0.0', debug=True, port=5005)
|
app.run(host='0.0.0.0', debug=True, port=5005)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from abc import ABCMeta, abstractmethod
|
|||||||
|
|
||||||
|
|
||||||
class CXGDriver(metaclass=ABCMeta):
|
class CXGDriver(metaclass=ABCMeta):
|
||||||
|
|
||||||
def __init__(self, data, schema=None, graph_method=None, diffexp_method=None):
|
def __init__(self, data, schema=None, graph_method=None, diffexp_method=None):
|
||||||
self.data = self._load_data(data)
|
self.data = self._load_data(data)
|
||||||
|
|
||||||
@@ -51,10 +50,8 @@ class CXGDriver(metaclass=ABCMeta):
|
|||||||
:param fields: list of keys for metadata to return, returns all metadata values if not set.
|
:param fields: list of keys for metadata to return, returns all metadata values if not set.
|
||||||
:return: Iterator for cellid + list of cells metadata values ex. [cell-id, val1, val2, val3]
|
:return: Iterator for cellid + list of cells metadata values ex. [cell-id, val1, val2, val3]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def create_graph(self, df):
|
def create_graph(self, df):
|
||||||
"""
|
"""
|
||||||
@@ -64,7 +61,6 @@ class CXGDriver(metaclass=ABCMeta):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def diffexp(self, df1, df2):
|
def diffexp(self, df1, df2):
|
||||||
"""
|
"""
|
||||||
@@ -72,7 +68,8 @@ class CXGDriver(metaclass=ABCMeta):
|
|||||||
|
|
||||||
:param df1: First set of cells
|
:param df1: First set of cells
|
||||||
:param df2: Second set of cells
|
:param df2: Second set of cells
|
||||||
:return: Up in the air: I recommend [gene name, mean_expression_cells1, mean_expression_cells2, average_difference, statistic_value]
|
:return: Up in the air: I recommend [gene name, mean_expression_cells1,
|
||||||
|
mean_expression_cells2, average_difference, statistic_value]
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ class ExpressionAPI(Resource):
|
|||||||
args = request.get_json()
|
args = request.get_json()
|
||||||
cell_list = args.get('celllist', [])
|
cell_list = args.get('celllist', [])
|
||||||
gene_list = args.get('genelist', [])
|
gene_list = args.get('genelist', [])
|
||||||
if not (cell_list) and not (gene_list):
|
if not cell_list and not gene_list:
|
||||||
return make_payload([], "must include celllist and/or genelist parameter", 400)
|
return make_payload([], "must include celllist and/or genelist parameter", 400)
|
||||||
|
|
||||||
expression_data = data.expression(cell_list, gene_list)
|
expression_data = data.expression(cell_list, gene_list)
|
||||||
@@ -327,6 +327,7 @@ class ExpressionAPI(Resource):
|
|||||||
|
|
||||||
return make_payload(expression_data)
|
return make_payload(expression_data)
|
||||||
|
|
||||||
|
|
||||||
class DifferentialExpressionAPI(Resource):
|
class DifferentialExpressionAPI(Resource):
|
||||||
@swagger.doc({
|
@swagger.doc({
|
||||||
'summary': 'Get the top expressed genes for two cell sets. Calculated using t-test',
|
'summary': 'Get the top expressed genes for two cell sets. Calculated using t-test',
|
||||||
@@ -429,6 +430,7 @@ class DifferentialExpressionAPI(Resource):
|
|||||||
data = data.diffexp(cell_list_1, cell_list_2, pval, num_genes)
|
data = data.diffexp(cell_list_1, cell_list_2, pval, num_genes)
|
||||||
return make_payload(data)
|
return make_payload(data)
|
||||||
|
|
||||||
|
|
||||||
def get_api_resources():
|
def get_api_resources():
|
||||||
bp = Blueprint('api', __name__, url_prefix='/api/v2.0')
|
bp = Blueprint('api', __name__, url_prefix='/api/v2.0')
|
||||||
api = Api(bp, add_api_spec_resource=False)
|
api = Api(bp, add_api_spec_resource=False)
|
||||||
@@ -436,4 +438,4 @@ def get_api_resources():
|
|||||||
api.add_resource(CellsAPI, "/cells")
|
api.add_resource(CellsAPI, "/cells")
|
||||||
api.add_resource(ExpressionAPI, "/expression")
|
api.add_resource(ExpressionAPI, "/expression")
|
||||||
api.add_resource(DifferentialExpressionAPI, "/diffexp")
|
api.add_resource(DifferentialExpressionAPI, "/diffexp")
|
||||||
return api
|
return api
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import scanpy.api as sc
|
|
||||||
import numpy as np
|
|
||||||
from scipy import stats
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import scanpy.api as sc
|
||||||
|
from scipy import stats
|
||||||
|
|
||||||
from ..util.schema_parse import parse_schema
|
from ..util.schema_parse import parse_schema
|
||||||
from ..driver.driver import CXGDriver
|
from ..driver.driver import CXGDriver
|
||||||
|
|
||||||
@@ -14,12 +15,10 @@ class ScanpyEngine(CXGDriver):
|
|||||||
self.schema = self._load_or_infer_schema(data, schema)
|
self.schema = self._load_or_infer_schema(data, schema)
|
||||||
self._set_cell_ids()
|
self._set_cell_ids()
|
||||||
self.cell_count = self.data.shape[0]
|
self.cell_count = self.data.shape[0]
|
||||||
# TODO Do I need this?
|
|
||||||
self.gene_count = self.data.shape[1]
|
self.gene_count = self.data.shape[1]
|
||||||
self.graph_method = graph_method
|
self.graph_method = graph_method
|
||||||
self.diffexp_method = diffexp_method
|
self.diffexp_method = diffexp_method
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _load_data(data):
|
def _load_data(data):
|
||||||
return sc.read(os.path.join(data, "data.h5ad"))
|
return sc.read(os.path.join(data, "data.h5ad"))
|
||||||
@@ -30,7 +29,7 @@ class ScanpyEngine(CXGDriver):
|
|||||||
if not schema:
|
if not schema:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
data_schema = parse_schema(os.path.join(data,schema))
|
data_schema = parse_schema(os.path.join(data, schema))
|
||||||
return data_schema
|
return data_schema
|
||||||
|
|
||||||
def _set_cell_ids(self):
|
def _set_cell_ids(self):
|
||||||
@@ -102,7 +101,6 @@ class ScanpyEngine(CXGDriver):
|
|||||||
metadata[idx]["CellName"] = metadata[idx].pop("cell_name", None)
|
metadata[idx]["CellName"] = metadata[idx].pop("cell_name", None)
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
def create_graph(self, df):
|
def create_graph(self, df):
|
||||||
"""
|
"""
|
||||||
Computes a n-d layout for cells through dimensionality reduction.
|
Computes a n-d layout for cells through dimensionality reduction.
|
||||||
@@ -112,12 +110,11 @@ class ScanpyEngine(CXGDriver):
|
|||||||
normalized_graph = (graph - graph.min()) / (graph.max() - graph.min())
|
normalized_graph = (graph - graph.min()) / (graph.max() - graph.min())
|
||||||
return np.hstack((df.obs["cell_name"].values.reshape(len(df.obs.index), 1), normalized_graph)).tolist()
|
return np.hstack((df.obs["cell_name"].values.reshape(len(df.obs.index), 1), normalized_graph)).tolist()
|
||||||
|
|
||||||
|
|
||||||
def diffexp(self, cell_list_1, cell_list_2, pval, num_genes):
|
def diffexp(self, cell_list_1, cell_list_2, pval, num_genes):
|
||||||
cells_idx_1 = np.in1d(self.data.obs["cell_name"], cell_list_1)
|
cells_idx_1 = np.in1d(self.data.obs["cell_name"], cell_list_1)
|
||||||
cells_idx_2 = np.in1d(self.data.obs["cell_name"], cell_list_2)
|
cells_idx_2 = np.in1d(self.data.obs["cell_name"], cell_list_2)
|
||||||
expression_1 = self.data.X[cells_idx_1,:]
|
expression_1 = self.data.X[cells_idx_1, :]
|
||||||
expression_2 = self.data.X[cells_idx_2,:]
|
expression_2 = self.data.X[cells_idx_2, :]
|
||||||
diff_exp = stats.ttest_ind(expression_1, expression_2)
|
diff_exp = stats.ttest_ind(expression_1, expression_2)
|
||||||
set1 = np.logical_and(diff_exp.pvalue < pval, diff_exp.statistic > 0)
|
set1 = np.logical_and(diff_exp.pvalue < pval, diff_exp.statistic > 0)
|
||||||
set2 = np.logical_and(diff_exp.pvalue < pval, diff_exp.statistic < 0)
|
set2 = np.logical_and(diff_exp.pvalue < pval, diff_exp.statistic < 0)
|
||||||
@@ -151,7 +148,7 @@ class ScanpyEngine(CXGDriver):
|
|||||||
"ave_diff": mean_diff2.tolist()[:num_genes]
|
"ave_diff": mean_diff2.tolist()[:num_genes]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def expression(self, cells=None, genes=None):
|
def expression(self, cells=None, genes=None):
|
||||||
"""
|
"""
|
||||||
:param df:
|
:param df:
|
||||||
@@ -185,11 +182,3 @@ class ScanpyEngine(CXGDriver):
|
|||||||
"cells": cell_data,
|
"cells": cell_data,
|
||||||
"nonzero_gene_count": int(np.sum(expression.any(axis=0)))
|
"nonzero_gene_count": int(np.sum(expression.any(axis=0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class QueryStringError(Exception):
|
class QueryStringError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _convert_variable(datatype, variable):
|
def _convert_variable(datatype, variable):
|
||||||
"""
|
"""
|
||||||
Convert variable to number (float/int)
|
Convert variable to number (float/int)
|
||||||
@@ -19,6 +20,7 @@ def _convert_variable(datatype, variable):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def parse_filter(filter, schema):
|
def parse_filter(filter, schema):
|
||||||
"""
|
"""
|
||||||
{key: variable_type
|
{key: variable_type
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from numpy import float32, integer
|
from numpy import float32, integer
|
||||||
from flask import make_response, jsonify, Response
|
from flask import make_response, jsonify, Response
|
||||||
|
|
||||||
|
|
||||||
class Float32JSONEncoder(json.JSONEncoder):
|
class Float32JSONEncoder(json.JSONEncoder):
|
||||||
def default(self, obj):
|
def default(self, obj):
|
||||||
if isinstance(obj, float32):
|
if isinstance(obj, float32):
|
||||||
@@ -10,6 +12,7 @@ class Float32JSONEncoder(json.JSONEncoder):
|
|||||||
return int(obj)
|
return int(obj)
|
||||||
return json.JSONEncoder.default(self, obj)
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
|
||||||
def make_payload(data, errormessage="", errorcode=200):
|
def make_payload(data, errormessage="", errorcode=200):
|
||||||
"""
|
"""
|
||||||
Creates JSON respons for requests
|
Creates JSON respons for requests
|
||||||
@@ -31,13 +34,7 @@ def make_payload(data, errormessage="", errorcode=200):
|
|||||||
}
|
}
|
||||||
}), errorcode)
|
}), errorcode)
|
||||||
|
|
||||||
|
|
||||||
def make_streaming_response(data_generator, errorcode=200, content_type="application/json"):
|
def make_streaming_response(data_generator, errorcode=200, content_type="application/json"):
|
||||||
# TODO headers
|
# TODO headers
|
||||||
return Response(data_generator, status=errorcode, content_type=content_type)
|
return Response(data_generator, status=errorcode, content_type=content_type)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from flask import (
|
from flask import (
|
||||||
Blueprint, render_template, request, url_for, current_app
|
Blueprint, render_template, url_for, current_app
|
||||||
)
|
)
|
||||||
|
|
||||||
bp = Blueprint('webapp', __name__, template_folder='templates')
|
bp = Blueprint('webapp', __name__, template_folder='templates')
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
url_base = current_app.config["CXG_API_BASE"]
|
url_base = current_app.config["CXG_API_BASE"]
|
||||||
@@ -16,6 +17,7 @@ def index():
|
|||||||
def swag():
|
def swag():
|
||||||
return render_template("swagger.html")
|
return render_template("swagger.html")
|
||||||
|
|
||||||
|
|
||||||
# renders swagger documentation
|
# renders swagger documentation
|
||||||
@bp.route('/favicon.png')
|
@bp.route('/favicon.png')
|
||||||
def favicon():
|
def favicon():
|
||||||
|
|||||||
+898
-3
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user