Repository: scverse/scanpy

Issue:
highly_variable_genes n_top_genes option
Hi, 

I tried to run `sc.tl.highly_variable_genes` with `flavor=CellRanger` and `n_top_genes = 2000`.  I obtained the following error:
```pytb
/home/miniconda3/envs/dev/lib/python3.7/site-packages/scanpy/preprocessing/_highly_variable_genes.py in highly_variable_genes(adata, min_disp, max_disp, min_mean, max_mean, n_top_genes, n_bins, flavor, subset, inplace, batch_key)
    280                 n_top_genes=n_top_genes,
    281                 n_bins=n_bins,
--> 282                 flavor=flavor,
    283             )
    284 

/home/miniconda3/envs/dev/lib/python3.7/site-packages/scanpy/preprocessing/_highly_variable_genes.py in _highly_variable_genes_single_batch(adata, min_disp, max_disp, min_mean, max_mean, n_top_genes, n_bins, flavor)
    141         dispersion_norm = dispersion_norm[~np.isnan(dispersion_norm)]
    142         dispersion_norm[::-1].sort()  # interestingly, np.argpartition is slightly slower
--> 143         disp_cut_off = dispersion_norm[n_top_genes-1]
    144         gene_subset = np.nan_to_num(df['dispersions_norm'].values) >= disp_cut_off
    145         logg.debug(

IndexError: index 1999 is out of bounds for axis 0 with size 1898
```

I run scanpy in Python 3.7 (linux machine) with the following versions:
```
scanpy==1.4.5.dev114+gd69832a anndata==0.6.22.post1 umap==0.3.9 numpy==1.17.0 scipy==1.3.0 pandas==0.25.0 scikit-learn==0.21.2 statsmodels==0.10.1 python-igraph==0.7.1 louvain==0.6.1
```

I suggest to check if `n_top_genes` is larger than `len(dispersion_norm)`.


Discussion:

Resolving patch:
diff --git a/scanpy/preprocessing/_highly_variable_genes.py b/scanpy/preprocessing/_highly_variable_genes.py
--- a/scanpy/preprocessing/_highly_variable_genes.py
+++ b/scanpy/preprocessing/_highly_variable_genes.py
@@ -6,11 +6,12 @@
 from anndata import AnnData
 
 from .. import logging as logg
-from ._distributed import materialize_as_ndarray
-from ._utils import _get_mean_var
+from .._settings import settings, Verbosity
 from .._utils import sanitize_anndata
+from ._utils import _get_mean_var
+from ._distributed import materialize_as_ndarray
 from ._simple import filter_genes
-from .._settings import settings, Verbosity
+
 
 def _highly_variable_genes_single_batch(
     adata: AnnData,
@@ -22,7 +23,8 @@ def _highly_variable_genes_single_batch(
     n_bins=20,
     flavor='seurat',
 ) -> pd.DataFrame:
-    """Internal function for annotating highly variable genes [Satija15]_ [Zheng17]_.
+    """\
+    Internal function for annotating highly variable genes [Satija15]_ [Zheng17]_.
 
     Expects logarithmized data.
 
@@ -69,8 +71,9 @@ def _highly_variable_genes_single_batch(
         A DataFrame that contains colums highly_variable, means, dispersions and dispersions_norm.
     """
 
-    if n_top_genes is not None and not all([
-            min_disp is None, max_disp is None, min_mean is None, max_mean is None]):
+    if n_top_genes is not None and not all(m is None for m in [
+        min_disp, max_disp, min_mean, max_mean
+    ]):
         logg.info('If you pass `n_top_genes`, all cutoffs are ignored.')
 
     if min_disp is None: min_disp = 0.5
@@ -140,6 +143,9 @@ def _highly_variable_genes_single_batch(
     if n_top_genes is not None:
         dispersion_norm = dispersion_norm[~np.isnan(dispersion_norm)]
         dispersion_norm[::-1].sort()  # interestingly, np.argpartition is slightly slower
+        if n_top_genes > adata.n_vars:
+            logg.info(f'`n_top_genes` > `adata.n_var`, returning all genes.')
+            n_top_genes = adata.n_vars
         disp_cut_off = dispersion_norm[n_top_genes-1]
         gene_subset = np.nan_to_num(df['dispersions_norm'].values) >= disp_cut_off
         logg.debug(


Test patch: