integrate prepare cli (#401)

* move prepare into main CLI as subcommand

* naming and formatting tweaks to better match launch subcommand
This commit is contained in:
Jeremy Freeman
2018-11-03 10:48:05 -04:00
committed by GitHub
parent 0c8a07ac13
commit e2d864a336
2 changed files with 45 additions and 42 deletions
+2
View File
@@ -1,6 +1,7 @@
import click
from .launch import launch
from .prepare import prepare
@click.group(name='cellxgene', context_settings=dict(max_content_width=85))
@@ -10,3 +11,4 @@ def cli():
cli.add_command(launch)
cli.add_command(prepare)
+43 -42
View File
@@ -4,28 +4,33 @@ from numpy import unique, ndarray
from scipy.sparse.csc import csc_matrix
from os.path import isfile, isdir, splitext, expanduser, sep
settings = dict(help_option_names=['-h', '--help'])
@click.command()
@click.argument('dataset', nargs=1, metavar='<dataset: file or path to data>', required=True)
@click.argument('data', nargs=1, metavar='<dataset: file or path to data>', required=True)
@click.option('--layout', '-l', default=['umap', 'tsne'], multiple=True, type=click.Choice(['umap', 'tsne']),
help='layout algorithm', show_default=True)
help='Layout algorithm', show_default=True)
@click.option('--recipe', '-r', default='none', type=click.Choice(['none', 'seurat', 'zheng17']),
help='preprocessing to run', show_default=True)
@click.option('--output', '-o', default='', help='save a new file to filename', metavar='<filename>')
@click.option('--set-obs-names', default='', help='named field to set as index for obs', metavar='<name>')
@click.option('--set-var-names', default='', help='named field to set as index for var', metavar='<name>')
@click.option('--make-obs-names-unique', default=True, is_flag=True, help='ensure obs index is unique', show_default=True)
@click.option('--make-var-names-unique', default=True, is_flag=True, help='ensure var index is unique', show_default=True)
@click.option('--sparse', default=False, is_flag=True, help='whether to force sparsity', show_default=True)
@click.option('--overwriting', default=False, is_flag=True, help='whether to allow file overwriting', show_default=True)
@click.option('--plotting', '-p', default=False, is_flag=True, help='whether to generate plots', show_default=True)
def cli(dataset, layout, recipe, output, set_obs_names, set_var_names,
make_obs_names_unique, make_var_names_unique, sparse, overwriting, plotting):
"""
preprocesses data for use with cellxgene
"""
help='Preprocessing to run.', show_default=True)
@click.option('--output', '-o', default='', help='Save a new file to filename.', metavar='<filename>')
@click.option('--plotting', '-p', default=False, is_flag=True, help='Whether to generate plots.', show_default=True)
@click.option('--sparse', default=False, is_flag=True, help='Whether to force sparsity.', show_default=True)
@click.option('--overwrite', default=False, is_flag=True, help='Allow file overwriting.', show_default=True)
@click.option('--set-obs-names', default='', help='Named field to set as index for obs.', metavar='<name>')
@click.option('--set-var-names', default='', help='Named field to set as index for var.', metavar='<name>')
@click.option('--make-obs-names-unique', default=True, is_flag=True,
help='Ensure obs index is unique.', show_default=True)
@click.option('--make-var-names-unique', default=True, is_flag=True,
help='Ensure var index is unique.', show_default=True)
def prepare(data, layout, recipe, output, plotting, sparse, overwrite,
set_obs_names, set_var_names, make_obs_names_unique, make_var_names_unique):
"""Preprocesses data for use with cellxgene.
This tool runs a series of scanpy routines for preparing a dataset
for use with cellxgene. It loads data from different formats
(h5ad, loom, or a 10x directory), runs dimensionality reduction,
computes nearest neighbors, computes a layout, performs clustering,
and saves the results. Includes additional options for naming
annotations, ensuring sparsity, and plotting results."""
# collect slow imports here to make CLI startup more responsive
click.echo('[cellxgene] Starting CLI...')
@@ -43,31 +48,31 @@ def cli(dataset, layout, recipe, output, set_obs_names, set_var_names,
output = expanduser(output)
if isfile(output) and not overwrite:
raise click.UsageError('Cannot overwrite existing file %s, try using the flag --overwrite' % output)
raise click.UsageError(f'Cannot overwrite existing file {output}, try using the flag --overwrite')
def load_data(dataset):
if isfile(dataset):
name, extension = splitext(dataset)
def load_data(data):
if isfile(data):
name, extension = splitext(data)
if extension == '.h5ad':
adata = sc.read_h5ad(dataset)
adata = sc.read_h5ad(data)
elif extension == '.loom':
adata = sc.read_loom(dataset)
adata = sc.read_loom(data)
else:
raise click.FileError(dataset, hint='does not have a valid extension [.h5ad | .loom]')
elif isdir(dataset):
if not dataset.endswith(sep):
dataset += sep
adata = sc.read_10x_mtx(dataset)
raise click.FileError(data, hint='does not have a valid extension [.h5ad | .loom]')
elif isdir(data):
if not data.endswith(sep):
data += sep
adata = sc.read_10x_mtx(data)
else:
raise click.FileError(dataset, hint='not a valid file or path')
raise click.FileError(data, hint='not a valid file or path')
if not set_obs_names == '':
if set_obs_names not in adata.obs_keys():
raise click.UsageError('obs %s not found, options are: %s' % (set_obs_names, adata.obs_keys()))
raise click.UsageError(f'obs {set_obs_names} not found, options are: {adata.obs_keys()}')
adata.obs_names = adata.obs[set_obs_names]
if not set_var_names == '':
if set_var_names not in adata.var_keys():
raise click.UsageError('var %s not found, options are: %s' % (set_var_names, adata.var_keys()))
raise click.UsageError(f'var {set_var_names} not found, options are: {adata.var_keys()}')
adata.var_names = adata.var[set_var_names]
if make_obs_names_unique:
adata.obs_names_make_unique()
@@ -115,12 +120,12 @@ def cli(dataset, layout, recipe, output, set_obs_names, set_var_names,
else:
palette = 'tab20'
if layout == 'umap' or layout == 'umap+tsne':
if 'umap' in layout:
sc.tl.umap(adata)
if plotting:
sc.pl.umap(adata, color='louvain', palette=palette, save='_louvain')
if layout == 'tsne' or layout == 'umap+tsne':
if 'tsne' in layout:
sc.tl.tsne(adata)
if plotting:
sc.pl.tsne(adata, color='louvain', palette=palette, save='_louvain')
@@ -139,8 +144,8 @@ def cli(dataset, layout, recipe, output, set_obs_names, set_var_names,
steps = [make_sparse, run_recipe, run_pca, run_neighbors, run_louvain, run_layout]
click.echo('[cellxgene] Loading data from %s, please wait...' % dataset)
adata = load_data(dataset)
click.echo(f'[cellxgene] Loading data from {data}, please wait...')
adata = load_data(data)
click.echo('[cellxgene] Beginning preprocessing...')
with click.progressbar(steps, label='[cellxgene] Progress', show_eta=False, item_show_func=show_step) as bar:
@@ -149,11 +154,7 @@ def cli(dataset, layout, recipe, output, set_obs_names, set_var_names,
# saving
if not output == '':
click.echo('[cellxgene] Saving results to %s...' % output)
click.echo(f'[cellxgene] Saving results to {output}...')
adata.write(output)
click.echo('[cellxgene] ' + click.style('Success!', fg='green'))
if __name__ == '__main__':
cli()
click.echo('[cellxgene] Success!')