Style guide cleanup

This commit is contained in:
Charlotte Weaver
2018-06-22 17:43:10 -07:00
parent 15ce4cc338
commit ca16447115
8 changed files with 930 additions and 45 deletions
+9 -8
View File
@@ -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 -5
View File
@@ -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
+4 -2
View File
@@ -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
+8 -19
View File
@@ -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)))
} }
+2
View File
@@ -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
+4 -7
View File
@@ -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)
+3 -1
View File
@@ -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():
File diff suppressed because one or more lines are too long