malva-client 0.3.2__tar.gz → 0.3.4__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.
Files changed (28) hide show
  1. {malva_client-0.3.2 → malva_client-0.3.4}/CHANGELOG.md +15 -0
  2. {malva_client-0.3.2/malva_client.egg-info → malva_client-0.3.4}/PKG-INFO +28 -24
  3. {malva_client-0.3.2 → malva_client-0.3.4}/README.md +27 -23
  4. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/__init__.py +1 -1
  5. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/client.py +604 -43
  6. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/models.py +126 -40
  7. {malva_client-0.3.2 → malva_client-0.3.4/malva_client.egg-info}/PKG-INFO +28 -24
  8. {malva_client-0.3.2 → malva_client-0.3.4}/pyproject.toml +1 -1
  9. {malva_client-0.3.2 → malva_client-0.3.4}/tests/test_client.py +212 -81
  10. {malva_client-0.3.2 → malva_client-0.3.4}/tests/test_models.py +61 -9
  11. {malva_client-0.3.2 → malva_client-0.3.4}/LICENSE +0 -0
  12. {malva_client-0.3.2 → malva_client-0.3.4}/MANIFEST.in +0 -0
  13. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/auth.py +0 -0
  14. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/cli.py +0 -0
  15. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/config.py +0 -0
  16. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/exceptions.py +0 -0
  17. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/storage.py +0 -0
  18. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client/tools.py +0 -0
  19. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client.egg-info/SOURCES.txt +0 -0
  20. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client.egg-info/dependency_links.txt +0 -0
  21. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client.egg-info/entry_points.txt +0 -0
  22. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client.egg-info/requires.txt +0 -0
  23. {malva_client-0.3.2 → malva_client-0.3.4}/malva_client.egg-info/top_level.txt +0 -0
  24. {malva_client-0.3.2 → malva_client-0.3.4}/requirements.txt +0 -0
  25. {malva_client-0.3.2 → malva_client-0.3.4}/setup.cfg +0 -0
  26. {malva_client-0.3.2 → malva_client-0.3.4}/tests/test_config.py +0 -0
  27. {malva_client-0.3.2 → malva_client-0.3.4}/tests/test_exceptions.py +0 -0
  28. {malva_client-0.3.2 → malva_client-0.3.4}/tests/test_storage.py +0 -0
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.4] - 2026-06-05
9
+ ### Added
10
+ - Coverage APIs accept `stage_callback` and log separate search, server-result generation, download, and parse stages for large coverage responses.
11
+ - `get_cells_by_metadata()` for search-independent all-cell denominator retrieval by sample and/or cell type. Database-wide retrieval is available with explicit `include_all_database_cells=True`.
12
+ - Aggregate result columns now use a single Expression Explorer-style schema: `rel`, `exp`, `pct`, `raw_kmers`, and `cell_count`. Legacy expression names are still accepted by helper methods such as `aggregate_by(..., expr_column=...)` when they can be mapped unambiguously.
13
+
14
+ ### Changed
15
+ - Quickstart and tutorials now avoid placeholder sample IDs and document the meaning of aggregate and per-cell expression values.
16
+ - `retrieve_cells()` documentation clarifies that denominator cells should be fetched independently with `get_cells_by_metadata()`, while fallback positive-cell-only endpoints may report `value=1`.
17
+ - All-cell metadata decoding uses categorical cell types and rounded/clipped `uint16` total counts for lower memory use and faster DataFrame construction.
18
+
19
+ ### Fixed
20
+ - `retrieve_cells()` now prefers the direct msgpack per-cell expression values endpoint, which uses the same raw k-mer value resolver as the Explorer matrix export without generating a ZIP. Aggregate searches therefore return raw per-cell values instead of all `1.0` positive indicators when values are available.
21
+ - Removed stale docs examples that produced errors with placeholder IDs or non-existent tutorial links.
22
+
8
23
  ## [0.3.2] - 2026-05-07
9
24
  ### Added
10
25
  - `retrieve_cells()` for direct per-cell retrieval from an existing search job,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: malva-client
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Python client for Malva Index
5
5
  Author-email: Daniel León-Periñán <daniel.leonperinan@mdc-berlin.de>, Nikos Karaiskos <nikolaos.karaiskos@mdc-berlin.de>
6
6
  Maintainer-email: Daniel León-Periñán <daniel.leonperinan@mdc-berlin.de>, Nikos Karaiskos <nikolaos.karaiskos@mdc-berlin.de>
@@ -89,8 +89,8 @@ malva_client config --server https://malva.mdc-berlin.de --token YOUR_API_TOKEN
89
89
 
90
90
  ```bash
91
91
  malva_client search "CD3D" --output results.csv
92
- malva_client search "ATCGATCGATCGATCGATCGATCG" --format json
93
- malva_client search "CD4 T cells in brain tissue"
92
+ malva_client search "ATCGATCGATCGATCGATCGATCG" --output sequence_results.json --format json
93
+ malva_client search "CD4 T cells in brain tissue" --output nl_results.csv --format csv
94
94
  ```
95
95
 
96
96
  ## Quick Start (Python)
@@ -98,17 +98,15 @@ malva_client search "CD4 T cells in brain tissue"
98
98
  ```python
99
99
  from malva_client import MalvaClient
100
100
 
101
- client = MalvaClient("https://malva.mdc-berlin.de", "YOUR_API_TOKEN")
101
+ client = MalvaClient()
102
102
 
103
- # Search for genes, sequences, or natural language queries
103
+ # Search for a gene and inspect aggregate expression rows
104
104
  results = client.search("CD3D")
105
- print(results)
105
+ print(results.df.head())
106
106
 
107
- # Search for sequences
108
- results = client.search("ATCGATCGATCGCCACATGGACTTGAC")
109
-
110
- # Natural language queries
111
- results = client.search("cells expressing markers of neurodegeneration")
107
+ # Search a DNA sequence of at least 24 nt
108
+ sequence_results = client.search_sequences("ATCGATCGATCGATCGATCGATCG")
109
+ print(sequence_results.df.head())
112
110
  ```
113
111
 
114
112
  ### Per-cell matrices
@@ -118,18 +116,22 @@ results = client.search("cells expressing markers of neurodegeneration")
118
116
  result = client.search("SPP1")
119
117
 
120
118
  # Retrieve positive cells from that search job
121
- cells = client.retrieve_cells(result, sample_ids=[123456])
122
-
123
- # Inspect positive cells or project them onto a coexpression index
124
- cell_ids = cells.get_cell_ids(sample_ids=[123456])
125
- coexpr = cells.project("human_cortex", sample_ids=[123456], top_n_genes=50)
126
-
127
- # If you only need projection, keep the cell transfer server-side
128
- coexpr = client.get_coexpression(result.job_id, "human_cortex", filter_sample_ids=[123456])
129
-
130
- # If downstream code needs per-feature cell values, store them in the search job
131
- value_result = client.search("SPP1", aggregate_expression=False)
132
- value_cells = client.retrieve_cells(value_result, sample_ids=[123456])
119
+ cells = client.retrieve_cells(result, include_sample_metadata=False)
120
+ sample_id = int(cells.cells.iloc[0]["sample_id"])
121
+
122
+ # Inspect cells from one real encoded sample ID
123
+ sample_cells = client.retrieve_cells(result, sample_ids=[sample_id], include_sample_metadata=True)
124
+ cell_ids = sample_cells.get_cell_ids()
125
+ cell_df = sample_cells.to_dataframe(include_sample_metadata=True)
126
+ print(cell_ids.head())
127
+ print(cell_df.head())
128
+
129
+ # Fetch all cells for that sample once from metadata for denominator analyses
130
+ all_cells = client.get_cells_by_metadata(sample_ids=[sample_id])
131
+ print(all_cells.head())
132
+
133
+ # Full-database retrieval is also available; it queues a server-side export.
134
+ # all_cells = client.get_cells_by_metadata(include_all_database_cells=True)
133
135
  ```
134
136
 
135
137
  ### Working with Results
@@ -137,10 +139,12 @@ value_cells = client.retrieve_cells(value_result, sample_ids=[123456])
137
139
  ```python
138
140
  # Enrich results with metadata
139
141
  results.enrich_with_metadata()
140
- fig = results.plot_expression_summary("cell_type")
141
142
 
142
143
  # Filter and aggregate
143
144
  filtered = results.filter_by(disease='normal', organ='brain')
145
+ by_cell_type = results.aggregate_by('cell_type', agg_func='mean')
146
+ print(filtered.df.head())
147
+ print(by_cell_type.head())
144
148
  ```
145
149
 
146
150
  See the [tutorials](https://malva-client.readthedocs.io/en/latest/tutorials.html) for coverage analysis, dataset discovery, cell-level searches, and more.
@@ -31,8 +31,8 @@ malva_client config --server https://malva.mdc-berlin.de --token YOUR_API_TOKEN
31
31
 
32
32
  ```bash
33
33
  malva_client search "CD3D" --output results.csv
34
- malva_client search "ATCGATCGATCGATCGATCGATCG" --format json
35
- malva_client search "CD4 T cells in brain tissue"
34
+ malva_client search "ATCGATCGATCGATCGATCGATCG" --output sequence_results.json --format json
35
+ malva_client search "CD4 T cells in brain tissue" --output nl_results.csv --format csv
36
36
  ```
37
37
 
38
38
  ## Quick Start (Python)
@@ -40,17 +40,15 @@ malva_client search "CD4 T cells in brain tissue"
40
40
  ```python
41
41
  from malva_client import MalvaClient
42
42
 
43
- client = MalvaClient("https://malva.mdc-berlin.de", "YOUR_API_TOKEN")
43
+ client = MalvaClient()
44
44
 
45
- # Search for genes, sequences, or natural language queries
45
+ # Search for a gene and inspect aggregate expression rows
46
46
  results = client.search("CD3D")
47
- print(results)
47
+ print(results.df.head())
48
48
 
49
- # Search for sequences
50
- results = client.search("ATCGATCGATCGCCACATGGACTTGAC")
51
-
52
- # Natural language queries
53
- results = client.search("cells expressing markers of neurodegeneration")
49
+ # Search a DNA sequence of at least 24 nt
50
+ sequence_results = client.search_sequences("ATCGATCGATCGATCGATCGATCG")
51
+ print(sequence_results.df.head())
54
52
  ```
55
53
 
56
54
  ### Per-cell matrices
@@ -60,18 +58,22 @@ results = client.search("cells expressing markers of neurodegeneration")
60
58
  result = client.search("SPP1")
61
59
 
62
60
  # Retrieve positive cells from that search job
63
- cells = client.retrieve_cells(result, sample_ids=[123456])
64
-
65
- # Inspect positive cells or project them onto a coexpression index
66
- cell_ids = cells.get_cell_ids(sample_ids=[123456])
67
- coexpr = cells.project("human_cortex", sample_ids=[123456], top_n_genes=50)
68
-
69
- # If you only need projection, keep the cell transfer server-side
70
- coexpr = client.get_coexpression(result.job_id, "human_cortex", filter_sample_ids=[123456])
71
-
72
- # If downstream code needs per-feature cell values, store them in the search job
73
- value_result = client.search("SPP1", aggregate_expression=False)
74
- value_cells = client.retrieve_cells(value_result, sample_ids=[123456])
61
+ cells = client.retrieve_cells(result, include_sample_metadata=False)
62
+ sample_id = int(cells.cells.iloc[0]["sample_id"])
63
+
64
+ # Inspect cells from one real encoded sample ID
65
+ sample_cells = client.retrieve_cells(result, sample_ids=[sample_id], include_sample_metadata=True)
66
+ cell_ids = sample_cells.get_cell_ids()
67
+ cell_df = sample_cells.to_dataframe(include_sample_metadata=True)
68
+ print(cell_ids.head())
69
+ print(cell_df.head())
70
+
71
+ # Fetch all cells for that sample once from metadata for denominator analyses
72
+ all_cells = client.get_cells_by_metadata(sample_ids=[sample_id])
73
+ print(all_cells.head())
74
+
75
+ # Full-database retrieval is also available; it queues a server-side export.
76
+ # all_cells = client.get_cells_by_metadata(include_all_database_cells=True)
75
77
  ```
76
78
 
77
79
  ### Working with Results
@@ -79,10 +81,12 @@ value_cells = client.retrieve_cells(value_result, sample_ids=[123456])
79
81
  ```python
80
82
  # Enrich results with metadata
81
83
  results.enrich_with_metadata()
82
- fig = results.plot_expression_summary("cell_type")
83
84
 
84
85
  # Filter and aggregate
85
86
  filtered = results.filter_by(disease='normal', organ='brain')
87
+ by_cell_type = results.aggregate_by('cell_type', agg_func='mean')
88
+ print(filtered.df.head())
89
+ print(by_cell_type.head())
86
90
  ```
87
91
 
88
92
  See the [tutorials](https://malva-client.readthedocs.io/en/latest/tutorials.html) for coverage analysis, dataset discovery, cell-level searches, and more.
@@ -6,7 +6,7 @@ try:
6
6
  from importlib.metadata import version as _get_version
7
7
  __version__ = _get_version("malva_client")
8
8
  except Exception:
9
- __version__ = "0.3.2"
9
+ __version__ = "0.3.4"
10
10
  __author__ = "Malva Team"
11
11
  __email__ = "hello@malva.bio"
12
12