mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-25 10:18:11 +08:00
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.
139 lines
4.3 KiB
Python
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
|