pyadata-cli 0.7.1__tar.gz → 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/PKG-INFO +4 -3
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/README.md +3 -2
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/pyproject.toml +1 -1
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/cli.py +40 -11
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/import_data.py +3 -1
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/conversion/__init__.py +46 -5
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/conversion/base.py +4 -0
- pyadata_cli-0.9.0/src/adata/conversion/cellbender.py +657 -0
- pyadata_cli-0.9.0/src/adata/conversion/features.py +380 -0
- pyadata_cli-0.9.0/src/adata/conversion/mtx.py +605 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/conversion/tenx.py +73 -294
- pyadata_cli-0.9.0/src/adata/core/csr_build.py +377 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/recast.py +19 -102
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/subset.py +6 -2
- pyadata_cli-0.9.0/src/adata/formats/mtx.py +481 -0
- pyadata_cli-0.9.0/src/adata/formats/sparse.py +152 -0
- pyadata_cli-0.9.0/src/adata/formats/textio.py +236 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/storage/__init__.py +2 -10
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/util/path.py +12 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/util/staging.py +5 -2
- pyadata_cli-0.7.1/src/adata/formats/sparse.py +0 -253
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/LICENSE +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/concat.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/convert.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/create.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/export.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/info.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/ls.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/recast.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/split.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/commands/subset.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/conversion/anndata_copy.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/concat.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/info.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/query.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/read.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/core/select.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/elements/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/elements/read.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/elements/spec.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/elements/strings.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/elements/write.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/array.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/common.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/dataframe.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/image.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/json_data.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/formats/validate.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/info.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/py.typed +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/read.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/util/__init__.py +0 -0
- {pyadata_cli-0.7.1 → pyadata_cli-0.9.0}/src/adata/util/names.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyadata-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Streaming CLI for exploring and editing large AnnData .h5ad and .zarr stores
|
|
5
5
|
Keywords: anndata,h5ad,zarr,bioinformatics,single-cell,cli
|
|
6
6
|
Author: Aljes Binkevich
|
|
@@ -48,7 +48,7 @@ A command-line tool for exploring huge AnnData stores (`.h5ad` and `.zarr`) with
|
|
|
48
48
|
- Auto-detects `.h5ad` files vs `.zarr` directories
|
|
49
49
|
- Chunked processing for dense and sparse matrices (CSR/CSC)
|
|
50
50
|
- Reads every AnnData on-disk layout, from 0.7.x through the current spec, and always writes the current one
|
|
51
|
-
- Converts between HDF5 and Zarr (v2 and v3) in either direction with `adata convert`, and to and from 10x Genomics HDF5 matrices
|
|
51
|
+
- Converts between HDF5 and Zarr (v2 and v3) in either direction with `adata convert`, and to and from 10x Genomics HDF5 matrices and 10x / STARsolo MTX folders, and from CellBender output
|
|
52
52
|
- Rich terminal output with progress indicators, kept on stderr so results pipe cleanly
|
|
53
53
|
|
|
54
54
|
**Documentation: [cellgeni.github.io/adata-cli](https://cellgeni.github.io/adata-cli/)**
|
|
@@ -96,7 +96,7 @@ Run help at any level (e.g. `adata --help`, `adata export --help`).
|
|
|
96
96
|
- `subset` – stream and write a filtered copy, selected by obs/var name lists (`--obs`/`--var`) or by expression (`--obs-query`/`--var-query`).
|
|
97
97
|
- `split` – write one store per distinct value of an annotation column, with a CSV manifest.
|
|
98
98
|
- `concat` – concatenate stores along the obs axis, with `--join inner|outer` and merge strategies for var and uns.
|
|
99
|
-
- `convert` – change a store's format: h5ad ↔ Zarr v2/v3,
|
|
99
|
+
- `convert` – change a store's format: h5ad ↔ Zarr v2/v3, 10x Genomics HDF5 (Cell Ranger's `*_feature_bc_matrix.h5`) and 10x / STARsolo MTX folders in and out, CellBender output in, streaming, with the output written beside its destination and moved into place only once complete.
|
|
100
100
|
- `recast` – change a matrix's dtype, layout (CSR/CSC/dense) or density, streaming; refuses a lossy cast or a large size increase unless forced. Called `convert` until 0.7.0.
|
|
101
101
|
- `export` – extract data from a store; subcommands: `dataframe` (any dataframe group to CSV), `array` (dense to `.npy`), `sparse` (CSR/CSC to `.mtx`), `dict` (JSON), `image` (PNG). Results go to stdout when no `--output` is given.
|
|
102
102
|
- `import` – write new data into a store at any path; subcommands: `dataframe` (CSV), `array` (`.npy`), `sparse` (`.mtx`), `dict` (JSON), `image` (PNG/JPEG/TIFF).
|
|
@@ -140,6 +140,7 @@ adata convert data.h5ad -o data.zarr
|
|
|
140
140
|
adata convert data.zarr -o data.h5ad --compression gzip
|
|
141
141
|
adata convert filtered_feature_bc_matrix.h5 -o counts.h5ad --feature-type "Gene Expression"
|
|
142
142
|
adata convert counts.h5ad -o for_cellbender.h5 --layer counts
|
|
143
|
+
adata convert Solo.out/Velocyto/raw -o velocyto.h5ad
|
|
143
144
|
```
|
|
144
145
|
|
|
145
146
|
## Documentation
|
|
@@ -8,7 +8,7 @@ A command-line tool for exploring huge AnnData stores (`.h5ad` and `.zarr`) with
|
|
|
8
8
|
- Auto-detects `.h5ad` files vs `.zarr` directories
|
|
9
9
|
- Chunked processing for dense and sparse matrices (CSR/CSC)
|
|
10
10
|
- Reads every AnnData on-disk layout, from 0.7.x through the current spec, and always writes the current one
|
|
11
|
-
- Converts between HDF5 and Zarr (v2 and v3) in either direction with `adata convert`, and to and from 10x Genomics HDF5 matrices
|
|
11
|
+
- Converts between HDF5 and Zarr (v2 and v3) in either direction with `adata convert`, and to and from 10x Genomics HDF5 matrices and 10x / STARsolo MTX folders, and from CellBender output
|
|
12
12
|
- Rich terminal output with progress indicators, kept on stderr so results pipe cleanly
|
|
13
13
|
|
|
14
14
|
**Documentation: [cellgeni.github.io/adata-cli](https://cellgeni.github.io/adata-cli/)**
|
|
@@ -56,7 +56,7 @@ Run help at any level (e.g. `adata --help`, `adata export --help`).
|
|
|
56
56
|
- `subset` – stream and write a filtered copy, selected by obs/var name lists (`--obs`/`--var`) or by expression (`--obs-query`/`--var-query`).
|
|
57
57
|
- `split` – write one store per distinct value of an annotation column, with a CSV manifest.
|
|
58
58
|
- `concat` – concatenate stores along the obs axis, with `--join inner|outer` and merge strategies for var and uns.
|
|
59
|
-
- `convert` – change a store's format: h5ad ↔ Zarr v2/v3,
|
|
59
|
+
- `convert` – change a store's format: h5ad ↔ Zarr v2/v3, 10x Genomics HDF5 (Cell Ranger's `*_feature_bc_matrix.h5`) and 10x / STARsolo MTX folders in and out, CellBender output in, streaming, with the output written beside its destination and moved into place only once complete.
|
|
60
60
|
- `recast` – change a matrix's dtype, layout (CSR/CSC/dense) or density, streaming; refuses a lossy cast or a large size increase unless forced. Called `convert` until 0.7.0.
|
|
61
61
|
- `export` – extract data from a store; subcommands: `dataframe` (any dataframe group to CSV), `array` (dense to `.npy`), `sparse` (CSR/CSC to `.mtx`), `dict` (JSON), `image` (PNG). Results go to stdout when no `--output` is given.
|
|
62
62
|
- `import` – write new data into a store at any path; subcommands: `dataframe` (CSV), `array` (`.npy`), `sparse` (`.mtx`), `dict` (JSON), `image` (PNG/JPEG/TIFF).
|
|
@@ -100,6 +100,7 @@ adata convert data.h5ad -o data.zarr
|
|
|
100
100
|
adata convert data.zarr -o data.h5ad --compression gzip
|
|
101
101
|
adata convert filtered_feature_bc_matrix.h5 -o counts.h5ad --feature-type "Gene Expression"
|
|
102
102
|
adata convert counts.h5ad -o for_cellbender.h5 --layer counts
|
|
103
|
+
adata convert Solo.out/Velocyto/raw -o velocyto.h5ad
|
|
103
104
|
```
|
|
104
105
|
|
|
105
106
|
## Documentation
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# so the distribution is published as `pyadata-cli`. The import package
|
|
4
4
|
# and the command are both still `adata`.
|
|
5
5
|
name = "pyadata-cli"
|
|
6
|
-
version = "0.
|
|
6
|
+
version = "0.9.0"
|
|
7
7
|
description = "Streaming CLI for exploring and editing large AnnData .h5ad and .zarr stores"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.12"
|
|
@@ -522,6 +522,8 @@ _CONVERT_FLAGS = {
|
|
|
522
522
|
"gene_ids_column": "--gene-ids-column",
|
|
523
523
|
"gene_names_column": "--gene-names-column",
|
|
524
524
|
"feature_types_column": "--feature-types-column",
|
|
525
|
+
"raw": "--raw",
|
|
526
|
+
"min_cell_probability": "--min-cell-probability",
|
|
525
527
|
}
|
|
526
528
|
|
|
527
529
|
#: Flags that only make sense for format conversion; with recast's flags,
|
|
@@ -553,7 +555,7 @@ def convert(
|
|
|
553
555
|
ctx: typer.Context,
|
|
554
556
|
file: Path = typer.Argument(
|
|
555
557
|
...,
|
|
556
|
-
help="Input file or
|
|
558
|
+
help="Input file, store, or 10x/STARsolo matrix folder",
|
|
557
559
|
exists=True,
|
|
558
560
|
readable=True,
|
|
559
561
|
dir_okay=True,
|
|
@@ -563,7 +565,8 @@ def convert(
|
|
|
563
565
|
None,
|
|
564
566
|
"--output",
|
|
565
567
|
"-o",
|
|
566
|
-
help="Output path; its extension picks the format (.h5ad, .zarr, .h5)"
|
|
568
|
+
help="Output path; its extension picks the format (.h5ad, .zarr, .h5), "
|
|
569
|
+
"or a folder with --to 10x-mtx",
|
|
567
570
|
dir_okay=True,
|
|
568
571
|
file_okay=True,
|
|
569
572
|
),
|
|
@@ -586,7 +589,7 @@ def convert(
|
|
|
586
589
|
None,
|
|
587
590
|
"--compression",
|
|
588
591
|
help="none, gzip or lzf for h5ad; none, gzip, zstd or blosc for zarr "
|
|
589
|
-
"(defaults to the source's)",
|
|
592
|
+
"(defaults to the source's); gzip or none for a 10x-mtx folder",
|
|
590
593
|
),
|
|
591
594
|
force: bool = typer.Option(
|
|
592
595
|
False,
|
|
@@ -601,7 +604,8 @@ def convert(
|
|
|
601
604
|
genome: Optional[str] = typer.Option(
|
|
602
605
|
None,
|
|
603
606
|
"--genome",
|
|
604
|
-
help="10x input: the genome to keep (picks the group
|
|
607
|
+
help="10x input: the genome to keep (picks the group or subfolder of a "
|
|
608
|
+
"Cell Ranger 2 matrix)",
|
|
605
609
|
),
|
|
606
610
|
var_names: str = typer.Option(
|
|
607
611
|
"gene_symbols",
|
|
@@ -643,6 +647,21 @@ def convert(
|
|
|
643
647
|
"--feature-types-column",
|
|
644
648
|
help="10x output: var column holding feature types (default feature_types)",
|
|
645
649
|
),
|
|
650
|
+
raw: Optional[Path] = typer.Option(
|
|
651
|
+
None,
|
|
652
|
+
"--raw",
|
|
653
|
+
help="CellBender input: the raw Cell Ranger .h5 it ran on, added as "
|
|
654
|
+
"layers['cellranger']",
|
|
655
|
+
exists=True,
|
|
656
|
+
dir_okay=False,
|
|
657
|
+
readable=True,
|
|
658
|
+
),
|
|
659
|
+
min_cell_probability: Optional[float] = typer.Option(
|
|
660
|
+
None,
|
|
661
|
+
"--min-cell-probability",
|
|
662
|
+
help="CellBender input: keep droplets with cell_probability at least "
|
|
663
|
+
"this (CellBender's own cutoff is 0.5)",
|
|
664
|
+
),
|
|
646
665
|
# Deprecated: recast's flags, so `convert` keeps working as it did until
|
|
647
666
|
# 1.0.0. Hidden from --help; the old matrix paths arrive in ctx.args.
|
|
648
667
|
inplace: bool = typer.Option(False, "--inplace", hidden=True),
|
|
@@ -657,11 +676,14 @@ def convert(
|
|
|
657
676
|
Convert a store to another format.
|
|
658
677
|
|
|
659
678
|
The output's extension picks the format: .h5ad, .zarr, or .h5 for a 10x
|
|
660
|
-
Genomics matrix (Cell Ranger's *_feature_bc_matrix.h5)
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
679
|
+
Genomics matrix (Cell Ranger's *_feature_bc_matrix.h5); --to 10x-mtx
|
|
680
|
+
writes a Matrix Market folder. Between h5ad and zarr every element is
|
|
681
|
+
copied, streamed, keeping the source's chunking and compression where the
|
|
682
|
+
target can express them. CellBender output keeps its latent variables, as
|
|
683
|
+
CellBender's own loader names them. A 10x matrix is read as scanpy's read_10x_h5 or
|
|
684
|
+
read_10x_mtx (gex_only=False) reads it, keeping integer counts, and
|
|
685
|
+
written as Cell Ranger writes it. MTX folders from Cell Ranger and
|
|
686
|
+
STARsolo, velocyto's included, are read in two streaming passes.
|
|
665
687
|
|
|
666
688
|
Nothing is written until every check has passed, and the output is moved
|
|
667
689
|
into place only once complete: a failed conversion leaves nothing
|
|
@@ -677,6 +699,11 @@ def convert(
|
|
|
677
699
|
adata convert filtered_feature_bc_matrix.h5 -o counts.h5ad
|
|
678
700
|
adata convert raw_feature_bc_matrix.h5 -o rna.h5ad --feature-type "Gene Expression"
|
|
679
701
|
adata convert counts.h5ad -o for_cellbender.h5 --layer counts
|
|
702
|
+
adata convert Solo.out/Gene/filtered -o counts.h5ad
|
|
703
|
+
adata convert Solo.out/Velocyto/raw -o velocyto.h5ad
|
|
704
|
+
adata convert counts.h5ad -o counts_mtx --to 10x-mtx --layer counts
|
|
705
|
+
adata convert cellbender_output.h5 -o cb.h5ad --raw raw_feature_bc_matrix.h5
|
|
706
|
+
adata convert cellbender_output.h5 -o cells.h5ad --min-cell-probability 0.5
|
|
680
707
|
"""
|
|
681
708
|
entries = list(ctx.args)
|
|
682
709
|
recast_flags = _given(ctx, _RECAST_FLAGS)
|
|
@@ -760,6 +787,8 @@ def convert(
|
|
|
760
787
|
gene_ids_column=gene_ids_column,
|
|
761
788
|
gene_names_column=gene_names_column,
|
|
762
789
|
feature_types_column=feature_types_column,
|
|
790
|
+
raw=raw,
|
|
791
|
+
min_cell_probability=min_cell_probability,
|
|
763
792
|
),
|
|
764
793
|
)
|
|
765
794
|
except Exception as e:
|
|
@@ -1117,7 +1146,7 @@ def export_sparse(
|
|
|
1117
1146
|
"--output",
|
|
1118
1147
|
"-o",
|
|
1119
1148
|
writable=True,
|
|
1120
|
-
help="Output .mtx file path (defaults to stdout)",
|
|
1149
|
+
help="Output .mtx file path; .mtx.gz gzips it (defaults to stdout)",
|
|
1121
1150
|
),
|
|
1122
1151
|
head: Optional[int] = typer.Option(
|
|
1123
1152
|
None, "--head", "-n", help="Output only the first n entries of mtx file"
|
|
@@ -1407,7 +1436,7 @@ def import_sparse(
|
|
|
1407
1436
|
..., help="Object path to create/replace (e.g., 'X', 'layers/counts')"
|
|
1408
1437
|
),
|
|
1409
1438
|
input_file: Path = typer.Argument(
|
|
1410
|
-
..., help="Input .mtx file", exists=True, readable=True
|
|
1439
|
+
..., help="Input .mtx or .mtx.gz file", exists=True, readable=True
|
|
1411
1440
|
),
|
|
1412
1441
|
output: Optional[Path] = typer.Option(
|
|
1413
1442
|
None,
|
|
@@ -60,7 +60,9 @@ def import_object(
|
|
|
60
60
|
console: Console,
|
|
61
61
|
) -> None:
|
|
62
62
|
target_file = _prepare_target_path(file, output_file, inplace, console)
|
|
63
|
-
|
|
63
|
+
suffixes = [x.lower() for x in input_file.suffixes]
|
|
64
|
+
# A gzipped matrix is still a matrix: `counts.mtx.gz` imports as `.mtx`.
|
|
65
|
+
ext = suffixes[-2] if len(suffixes) > 1 and suffixes[-1] == ".gz" else input_file.suffix.lower()
|
|
64
66
|
|
|
65
67
|
if ext not in EXTENSION_FORMAT:
|
|
66
68
|
raise ValueError(
|
|
@@ -17,7 +17,7 @@ from typing import Dict, FrozenSet, List, Optional
|
|
|
17
17
|
|
|
18
18
|
import h5py
|
|
19
19
|
|
|
20
|
-
from adata.conversion import tenx
|
|
20
|
+
from adata.conversion import cellbender, mtx, tenx
|
|
21
21
|
from adata.conversion.anndata_copy import AnnDataCopy
|
|
22
22
|
from adata.conversion.base import ConversionPlan, Converter, Format, Options
|
|
23
23
|
from adata.storage import has_valid_anndata_root_attrs, is_zarr_path
|
|
@@ -66,6 +66,15 @@ FORMATS: Dict[str, Format] = {
|
|
|
66
66
|
anndata=True,
|
|
67
67
|
sniff=is_zarr_path,
|
|
68
68
|
),
|
|
69
|
+
# Before 10x-h5: a CellBender file is a 10x matrix too, and the first
|
|
70
|
+
# sniffer to match wins. `--from 10x-h5` still reads one as plain 10x.
|
|
71
|
+
"cellbender": Format(
|
|
72
|
+
name="cellbender",
|
|
73
|
+
description="CellBender remove-background output (0.2 and later)",
|
|
74
|
+
extensions=(".h5",),
|
|
75
|
+
sniff=cellbender.sniff,
|
|
76
|
+
importer=cellbender.CellbenderImport(),
|
|
77
|
+
),
|
|
69
78
|
"10x-h5": Format(
|
|
70
79
|
name="10x-h5",
|
|
71
80
|
description="10x Genomics feature-barcode matrix (Cell Ranger v2 or v3)",
|
|
@@ -74,6 +83,15 @@ FORMATS: Dict[str, Format] = {
|
|
|
74
83
|
importer=tenx.TenxImport(),
|
|
75
84
|
exporter=tenx.TenxExport(),
|
|
76
85
|
),
|
|
86
|
+
# A folder, so no extension: chosen as output with `--to 10x-mtx`.
|
|
87
|
+
"10x-mtx": Format(
|
|
88
|
+
name="10x-mtx",
|
|
89
|
+
description="10x Genomics / STARsolo Matrix Market folder",
|
|
90
|
+
extensions=(),
|
|
91
|
+
sniff=mtx.sniff,
|
|
92
|
+
importer=mtx.MtxImport(),
|
|
93
|
+
exporter=mtx.MtxExport(),
|
|
94
|
+
),
|
|
77
95
|
}
|
|
78
96
|
|
|
79
97
|
_ANNDATA_COPY = AnnDataCopy()
|
|
@@ -106,6 +124,12 @@ def detect_format(path: Path) -> str:
|
|
|
106
124
|
for fmt in FORMATS.values():
|
|
107
125
|
if (fmt.anndata or fmt.sniff is None) and suffix in fmt.extensions:
|
|
108
126
|
return fmt.name
|
|
127
|
+
if suffix in (".mtx", ".gz") and path.name.lower().endswith((".mtx", ".mtx.gz")):
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"'{path.name}' is a single Matrix Market file, which `convert` "
|
|
130
|
+
"does not read on its own: give the folder holding it with its "
|
|
131
|
+
"barcodes and features, or use `adata import sparse`."
|
|
132
|
+
)
|
|
109
133
|
raise ValueError(
|
|
110
134
|
f"Cannot tell what format '{path}' is. Pass --from, one of: {_names()}."
|
|
111
135
|
)
|
|
@@ -121,24 +145,41 @@ def output_format(path: Path, requested: Optional[str] = None) -> str:
|
|
|
121
145
|
path = Path(path)
|
|
122
146
|
if requested is not None and requested not in FORMATS:
|
|
123
147
|
raise ValueError(f"Unknown format {requested!r}; use one of: {_names()}.")
|
|
148
|
+
if requested is not None and not (
|
|
149
|
+
FORMATS[requested].anndata or FORMATS[requested].exporter is not None
|
|
150
|
+
):
|
|
151
|
+
raise ValueError(f"{requested} can be read but not written.")
|
|
124
152
|
|
|
125
153
|
suffix = path.suffix.lower()
|
|
154
|
+
# Only formats that can be written: `.h5` names CellBender output too,
|
|
155
|
+
# but an `.h5` output is a 10x matrix.
|
|
126
156
|
by_extension = next(
|
|
127
|
-
(
|
|
157
|
+
(
|
|
158
|
+
fmt.name
|
|
159
|
+
for fmt in FORMATS.values()
|
|
160
|
+
if suffix in fmt.extensions and (fmt.anndata or fmt.exporter is not None)
|
|
161
|
+
),
|
|
162
|
+
None,
|
|
128
163
|
)
|
|
129
164
|
if requested is None:
|
|
130
165
|
if by_extension is None:
|
|
131
166
|
raise ValueError(
|
|
132
167
|
f"Cannot tell the output format from '{path.name}'. "
|
|
133
|
-
f"Use a known extension or pass --to, one of: {_names()}
|
|
168
|
+
f"Use a known extension or pass --to, one of: {_names()} "
|
|
169
|
+
"(--to 10x-mtx for a folder)."
|
|
134
170
|
)
|
|
135
171
|
return by_extension
|
|
136
172
|
|
|
137
173
|
if by_extension is not None and by_extension != requested:
|
|
174
|
+
extensions = FORMATS[requested].extensions
|
|
138
175
|
raise ValueError(
|
|
139
176
|
f"--to {requested} contradicts the output's extension, which means "
|
|
140
|
-
f"{by_extension}. Name the output
|
|
141
|
-
|
|
177
|
+
f"{by_extension}. Name the output "
|
|
178
|
+
+ (
|
|
179
|
+
f"with one of: {', '.join(extensions)}."
|
|
180
|
+
if extensions
|
|
181
|
+
else "as a folder, without an extension."
|
|
182
|
+
)
|
|
142
183
|
)
|
|
143
184
|
if (requested == "zarr") != (suffix == ".zarr"):
|
|
144
185
|
raise ValueError(
|
|
@@ -35,6 +35,10 @@ class Options:
|
|
|
35
35
|
gene_names_column: Optional[str] = None
|
|
36
36
|
feature_types_column: Optional[str] = None
|
|
37
37
|
|
|
38
|
+
# Reading CellBender output.
|
|
39
|
+
raw: Optional[Path] = None
|
|
40
|
+
min_cell_probability: Optional[float] = None
|
|
41
|
+
|
|
38
42
|
|
|
39
43
|
@dataclass
|
|
40
44
|
class ConversionPlan:
|