Files
cellxgene/server/common/app_config.py
T
bmccandless 907cc634f5 server refactor (#1140)
This PR contains a refactoring to make adding new features easier.

The new features include supporting the tiledb format, and the multi dataset application.

The refactoring includes

Simplifying the directory structure and files.
a class structure to handle annotations (currently one type: AnnotationsLocalFile).
a class to handle application configuration
a class structure to handle matrix data (currently AnndataAdaptor and CxgAdaptor). CxgAdaptor uses tiledb.
Algorithms that were previously dependent on the scanpy anndata object are now generalized to work with an abstract interface.
The multi dataset option is not fully supported yet, and so the option to use it is hidden.
Use "cli launch --dataroot ..."
To access this feature.

All combinations of app single dataset/ app multi dataset and AnndataAdaptor/CxgAdaptor work with all the features, such as annotations, ontologies, diffexp.
2020-02-19 10:22:35 -08:00

139 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
from server import __version__ as cellxgene_version
from os.path import basename, splitext
class AppFeature(object):
def __init__(self, path, available=False, method="POST", extra={}):
self.path = path
self.available = available
self.method = method
self.extra = extra
for k, v in extra.items():
setattr(self, k, v)
def todict(self):
d = dict(
available=self.available,
method=self.method,
path=self.path)
d.update(self.extra)
return d
class AppConfig(object):
def __init__(self, **kw):
super().__init__()
# app inputs
self.datapath = None
self.dataroot = None
self.title = ""
self.about = None
self.scripts = []
self.layout = None
self.max_category_items = 100
self.diffexp_lfc_cutoff = 0.01
self.disable_diffexp = False
self.anndata_backed = False
# TODO these options may not apply to all datasets in the multi dataset.
# may need to invent a way to associate these config parameters with
# specific datasets.
self.obs_names = None
self.var_names = None
# parameters
self.diffexp_may_be_slow = False
inputs = ["datapath", "dataroot", "title", "about", "scripts", "layout",
"max_category_items", "diffexp_lfc_cutoff",
"obs_names", "var_names",
"anndata_backed", "disable_diffexp"]
self.update(inputs, kw)
def update(self, inputs, kw):
for k, v in kw.items():
if k in inputs:
setattr(self, k, v)
else:
raise RuntimeError(f"unknown config parameter {k}.")
def get_title(self, data_adaptor):
if self.title:
return self.title
# TODO: find a place to stash the dataset title, such as a
# json file at the same location as the data matrix.
# for example, if the dataset is at abc.cxg then a file with
# the title and about info could be at abc.cxg.metadata.
# for now just return the basename
location = data_adaptor.get_location()
if location.endswith("/"):
location = location[:-1]
return splitext(basename(location))[0]
def get_about(self, data_adaptor):
return self.about
def get_config(self, data_adaptor, annotation=None):
# FIXME The current set of config is not consistently presented:
# we have camalCase, hyphen-text, and underscore_text
# features
features = [f.todict() for f in data_adaptor.get_features().values()]
# display_names
title = self.get_title(data_adaptor)
about = self.get_about(data_adaptor)
display_names = dict(
engine=data_adaptor.get_name(),
dataset=title)
# library_versions
library_versions = {}
library_versions.update(data_adaptor.get_library_versions())
library_versions["cellxgene"] = cellxgene_version
# links
links = {"about-dataset" : about}
# parameters
parameters = {
"layout": self.layout,
"max-category-items": self.max_category_items,
"obs_names": self.obs_names,
"var_names": self.var_names,
"diffexp_lfc_cutoff": self.diffexp_lfc_cutoff,
"backed": self.anndata_backed,
"disable-diffexp": self.disable_diffexp,
"annotations": False,
"annotations_file": None,
"annotations_output_dir": None,
"annotations_cell_ontology_enabled": False,
"annotations_cell_ontology_obopath": None,
"annotations_cell_ontology_terms": None,
"diffexp-may-be-slow": False,
}
data_adaptor.update_parameters(parameters)
if annotation:
annotation.update_parameters(parameters, data_adaptor)
# gather it all together
c = {}
config = c["config"] = {}
config["features"] = features
config["displayNames"] = display_names
config["library_versions"] = library_versions
config["links"] = links
config["parameters"] = parameters
return c