auroraomics 0.1.0.dev0__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.
- auroraomics-0.1.0.dev0/LICENSE +131 -0
- auroraomics-0.1.0.dev0/MANIFEST.in +7 -0
- auroraomics-0.1.0.dev0/PKG-INFO +134 -0
- auroraomics-0.1.0.dev0/README.md +95 -0
- auroraomics-0.1.0.dev0/pyproject.toml +91 -0
- auroraomics-0.1.0.dev0/setup.cfg +4 -0
- auroraomics-0.1.0.dev0/src/auroraomics/__init__.py +74 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/MANIFEST.json +11 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/genes/gene-table.2026-09-05.json +19368 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/public-api/golden-16-tiles.manifest.json +308 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/public-api-counters.tokens.json +28 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/public-api-input-kinds.tokens.json +71 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/public-api.tokens.json +345 -0
- auroraomics-0.1.0.dev0/src/auroraomics/_contracts/qc-thresholds.tokens.json +10 -0
- auroraomics-0.1.0.dev0/src/auroraomics/contracts.py +155 -0
- auroraomics-0.1.0.dev0/src/auroraomics/h5ad.py +398 -0
- auroraomics-0.1.0.dev0/src/auroraomics/pack.py +667 -0
- auroraomics-0.1.0.dev0/src/auroraomics/py.typed +0 -0
- auroraomics-0.1.0.dev0/src/auroraomics/qc.py +288 -0
- auroraomics-0.1.0.dev0/src/auroraomics/subsample.py +140 -0
- auroraomics-0.1.0.dev0/src/auroraomics.egg-info/PKG-INFO +134 -0
- auroraomics-0.1.0.dev0/src/auroraomics.egg-info/SOURCES.txt +23 -0
- auroraomics-0.1.0.dev0/src/auroraomics.egg-info/dependency_links.txt +1 -0
- auroraomics-0.1.0.dev0/src/auroraomics.egg-info/requires.txt +25 -0
- auroraomics-0.1.0.dev0/src/auroraomics.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# PolyForm Noncommercial License 1.0.0
|
|
2
|
+
|
|
3
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
4
|
+
|
|
5
|
+
## Acceptance
|
|
6
|
+
|
|
7
|
+
In order to get any license under these terms, you must agree
|
|
8
|
+
to them as both strict obligations and conditions to all
|
|
9
|
+
your licenses.
|
|
10
|
+
|
|
11
|
+
## Copyright License
|
|
12
|
+
|
|
13
|
+
The licensor grants you a copyright license for the
|
|
14
|
+
software to do everything you might do with the software
|
|
15
|
+
that would otherwise infringe the licensor's copyright
|
|
16
|
+
in it for any permitted purpose. However, you may
|
|
17
|
+
only distribute the software according to [Distribution
|
|
18
|
+
License](#distribution-license) and make changes or new works
|
|
19
|
+
based on the software according to [Changes and New Works
|
|
20
|
+
License](#changes-and-new-works-license).
|
|
21
|
+
|
|
22
|
+
## Distribution License
|
|
23
|
+
|
|
24
|
+
The licensor grants you an additional copyright license
|
|
25
|
+
to distribute copies of the software. Your license
|
|
26
|
+
to distribute covers distributing the software with
|
|
27
|
+
changes and new works permitted by [Changes and New Works
|
|
28
|
+
License](#changes-and-new-works-license).
|
|
29
|
+
|
|
30
|
+
## Notices
|
|
31
|
+
|
|
32
|
+
You must ensure that anyone who gets a copy of any part of
|
|
33
|
+
the software from you also gets a copy of these terms or the
|
|
34
|
+
URL for them above, as well as copies of any plain-text lines
|
|
35
|
+
beginning with `Required Notice:` that the licensor provided
|
|
36
|
+
with the software. For example:
|
|
37
|
+
|
|
38
|
+
> Required Notice: Copyright Kalin Nonchev / ETH Zurich (https://github.com/ratschlab/DeepSpotM)
|
|
39
|
+
|
|
40
|
+
## Changes and New Works License
|
|
41
|
+
|
|
42
|
+
The licensor grants you an additional copyright license to
|
|
43
|
+
make changes and new works based on the software for any
|
|
44
|
+
permitted purpose.
|
|
45
|
+
|
|
46
|
+
## Patent License
|
|
47
|
+
|
|
48
|
+
The licensor grants you a patent license for the software that
|
|
49
|
+
covers patent claims the licensor can license, or becomes able
|
|
50
|
+
to license, that you would infringe by using the software.
|
|
51
|
+
|
|
52
|
+
## Noncommercial Purposes
|
|
53
|
+
|
|
54
|
+
Any noncommercial purpose is a permitted purpose.
|
|
55
|
+
|
|
56
|
+
## Personal Uses
|
|
57
|
+
|
|
58
|
+
Personal use for research, experiment, and testing for
|
|
59
|
+
the benefit of public knowledge, personal study, private
|
|
60
|
+
entertainment, hobby projects, amateur pursuits, or religious
|
|
61
|
+
observance, without any anticipated commercial application,
|
|
62
|
+
is use for a permitted purpose.
|
|
63
|
+
|
|
64
|
+
## Noncommercial Organizations
|
|
65
|
+
|
|
66
|
+
Use by any charitable organization, educational institution,
|
|
67
|
+
public research organization, public safety or health
|
|
68
|
+
organization, environmental protection organization,
|
|
69
|
+
or government institution is use for a permitted purpose
|
|
70
|
+
regardless of the source of funding or obligations resulting
|
|
71
|
+
from the funding.
|
|
72
|
+
|
|
73
|
+
## Fair Use
|
|
74
|
+
|
|
75
|
+
You may have "fair use" rights for the software under the
|
|
76
|
+
law. These terms do not limit them.
|
|
77
|
+
|
|
78
|
+
## No Other Rights
|
|
79
|
+
|
|
80
|
+
These terms do not allow you to sublicense or transfer any of
|
|
81
|
+
your licenses to anyone else, or prevent the licensor from
|
|
82
|
+
granting licenses to anyone else. These terms do not imply
|
|
83
|
+
any other licenses.
|
|
84
|
+
|
|
85
|
+
## Patent Defense
|
|
86
|
+
|
|
87
|
+
If you make any written claim that the software infringes or
|
|
88
|
+
contributes to infringement of any patent, your patent license
|
|
89
|
+
for the software granted under these terms ends immediately. If
|
|
90
|
+
your company makes such a claim, your patent license ends
|
|
91
|
+
immediately for work on behalf of your company.
|
|
92
|
+
|
|
93
|
+
## Violations
|
|
94
|
+
|
|
95
|
+
The first time you are notified in writing that you have
|
|
96
|
+
violated any of these terms, or done anything with the software
|
|
97
|
+
not covered by your licenses, your licenses can nonetheless
|
|
98
|
+
continue if you come into full compliance with these terms,
|
|
99
|
+
and take practical steps to correct past violations, within
|
|
100
|
+
32 days of receiving notice. Otherwise, all your licenses
|
|
101
|
+
end immediately.
|
|
102
|
+
|
|
103
|
+
## No Liability
|
|
104
|
+
|
|
105
|
+
***As far as the law allows, the software comes as is, without
|
|
106
|
+
any warranty or condition, and the licensor will not be liable
|
|
107
|
+
to you for any damages arising out of these terms or the use
|
|
108
|
+
or nature of the software, under any kind of legal claim.***
|
|
109
|
+
|
|
110
|
+
## Definitions
|
|
111
|
+
|
|
112
|
+
The **licensor** is the individual or entity offering these
|
|
113
|
+
terms, and the **software** is the software the licensor makes
|
|
114
|
+
available under these terms.
|
|
115
|
+
|
|
116
|
+
**You** refers to the individual or entity agreeing to these
|
|
117
|
+
terms.
|
|
118
|
+
|
|
119
|
+
**Your company** is any legal entity, sole proprietorship,
|
|
120
|
+
or other kind of organization that you work for, plus all
|
|
121
|
+
organizations that have control over, are under the control of,
|
|
122
|
+
or are under common control with that organization. **Control**
|
|
123
|
+
means ownership of substantially all the assets of an entity,
|
|
124
|
+
or the power to direct its management and policies by vote,
|
|
125
|
+
contract, or otherwise. Control can be direct or indirect.
|
|
126
|
+
|
|
127
|
+
**Your licenses** are all the licenses granted to you for the
|
|
128
|
+
software under these terms.
|
|
129
|
+
|
|
130
|
+
**Use** means anything you do with the software requiring one
|
|
131
|
+
of your licenses.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# The published source distribution carries the package and its metadata, and
|
|
2
|
+
# nothing else. The tests only mean anything next to the checkout that defines
|
|
3
|
+
# the contracts — from an unpacked distribution they would skip — and every
|
|
4
|
+
# file that ships is a file the boundary guards have to keep clean forever.
|
|
5
|
+
# Smaller surface, same package. (The release scripts are outside the sdist's
|
|
6
|
+
# source list already, so they need no rule here.)
|
|
7
|
+
prune tests
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: auroraomics
|
|
3
|
+
Version: 0.1.0.dev0
|
|
4
|
+
Summary: Virtual spatial transcriptomics from H&E histology: patch QC, tile packing and the .h5ad result contract.
|
|
5
|
+
Author: Kalin Nonchev
|
|
6
|
+
License-Expression: PolyForm-Noncommercial-1.0.0
|
|
7
|
+
Keywords: histopathology,spatial-transcriptomics,h5ad,anndata,whole-slide-image
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
13
|
+
Classifier: Typing :: Typed
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: numpy>=1.23
|
|
18
|
+
Requires-Dist: h5py>=3.9
|
|
19
|
+
Requires-Dist: opencv-python-headless>=4.5
|
|
20
|
+
Requires-Dist: pillow>=9
|
|
21
|
+
Provides-Extra: client
|
|
22
|
+
Requires-Dist: httpx>=0.27; extra == "client"
|
|
23
|
+
Requires-Dist: pydantic>=2; extra == "client"
|
|
24
|
+
Requires-Dist: anndata>=0.10; extra == "client"
|
|
25
|
+
Provides-Extra: deepspotm
|
|
26
|
+
Provides-Extra: slide
|
|
27
|
+
Requires-Dist: tifffile>=2023.7.10; extra == "slide"
|
|
28
|
+
Requires-Dist: imagecodecs>=2023.3.16; extra == "slide"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
31
|
+
Requires-Dist: setuptools>=77; extra == "dev"
|
|
32
|
+
Requires-Dist: wheel; extra == "dev"
|
|
33
|
+
Requires-Dist: anndata<0.12,>=0.10; extra == "dev"
|
|
34
|
+
Requires-Dist: tifffile>=2023.7.10; extra == "dev"
|
|
35
|
+
Requires-Dist: imagecodecs>=2023.3.16; extra == "dev"
|
|
36
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: numpy<2; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# auroraomics
|
|
41
|
+
|
|
42
|
+
Virtual spatial transcriptomics from H&E histology.
|
|
43
|
+
|
|
44
|
+
This package holds the pieces of that pipeline that are pure Python, so the
|
|
45
|
+
same code runs on your laptop, in a GPU container and on the service:
|
|
46
|
+
|
|
47
|
+
- **`auroraomics.qc`** — the three patch-quality predicates (foreground, blur,
|
|
48
|
+
stained tissue) applied to every candidate tile before a model sees it, and
|
|
49
|
+
the short-circuiting cascade that combines them.
|
|
50
|
+
- **`auroraomics.pack`** — build the `patches` archive a prediction takes as
|
|
51
|
+
input (`pack_tiles`), and validate one you have been handed (`read_archive`).
|
|
52
|
+
- **`auroraomics.h5ad`** — write the standard `.h5ad` result with `h5py`
|
|
53
|
+
alone, streaming the expression matrix batch by batch so peak memory is one
|
|
54
|
+
batch rather than the whole matrix.
|
|
55
|
+
- **`auroraomics.subsample`** — pick the densest contiguous square of spots
|
|
56
|
+
when a slide yields more tiles than a run is allowed to spend.
|
|
57
|
+
- **`auroraomics.contracts`** — the shared contract values (container layout,
|
|
58
|
+
input-kind caps, result layout) as data, so nothing here re-types a number
|
|
59
|
+
the service also reads.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
pip install auroraomics
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The core needs only numpy, h5py, OpenCV and Pillow. Extras add the API client
|
|
68
|
+
(`client`), a local model runtime (`deepspotm`) and pyramidal slide reading
|
|
69
|
+
(`slide`).
|
|
70
|
+
|
|
71
|
+
## Pack tiles, then look at the report
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import auroraomics as ao
|
|
75
|
+
|
|
76
|
+
report = ao.pack_tiles(tiles, "sample.zip", mpp=0.499, thumbnail=thumb)
|
|
77
|
+
print(report.written, "tiles kept,", report.rejected, "dropped")
|
|
78
|
+
print(report.rejected_by_reason) # {'foreground_ratio': 12, ...}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`tiles` is any iterable of `ao.Tile(image, x, y)`, where `image` is an RGB
|
|
82
|
+
`uint8` array and `x`/`y` are the tile's top-left position in full-resolution
|
|
83
|
+
pixels. Tiles are quality-checked as they stream past, and only the ones that
|
|
84
|
+
pass are written, so an iterable that reads a slide lazily never has to hold
|
|
85
|
+
more than one tile in memory.
|
|
86
|
+
|
|
87
|
+
## Validate an archive before trusting it
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
archive = ao.read_archive("sample.zip") # raises ArchiveError on anything odd
|
|
91
|
+
for tile in archive.tiles(): # decoded one at a time
|
|
92
|
+
...
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`read_archive` checks the member names, the manifest, the tile geometry and the
|
|
96
|
+
declared sizes *before* decoding a single pixel, and refuses an archive whose
|
|
97
|
+
members do not match the container contract.
|
|
98
|
+
|
|
99
|
+
## Write a result
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
ao.write_result(
|
|
103
|
+
"result.h5ad",
|
|
104
|
+
obs=obs, # per-spot columns, as plain arrays
|
|
105
|
+
var=var, # per-gene columns, indexed by gene id
|
|
106
|
+
spatial=coords, # (n_spots, 2) array -> obsm["spatial"]
|
|
107
|
+
x=batches, # an array, or an iterable of row batches
|
|
108
|
+
uns={"model": {"id": "..."}},
|
|
109
|
+
layers={"image_only": other_batches},
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The file reads back as an ordinary `AnnData` in anndata 0.10 and 0.11. Passing
|
|
114
|
+
an iterable for `x` streams it: each batch is compressed into the file as it
|
|
115
|
+
arrives and then dropped, which is what makes a matrix larger than memory
|
|
116
|
+
writable.
|
|
117
|
+
|
|
118
|
+
## Typing
|
|
119
|
+
|
|
120
|
+
The package ships `py.typed`, so annotations are visible to type checkers in
|
|
121
|
+
your project.
|
|
122
|
+
|
|
123
|
+
## Licence
|
|
124
|
+
|
|
125
|
+
The code in this package is licensed under
|
|
126
|
+
[PolyForm Noncommercial 1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0),
|
|
127
|
+
which permits use for any purpose that is not commercial. It is the same licence the
|
|
128
|
+
model package this client is built for carries, so installing both puts you under one
|
|
129
|
+
rule rather than two.
|
|
130
|
+
|
|
131
|
+
The model weights are licensed separately by whoever publishes them, and access to them
|
|
132
|
+
may be gated. Read those terms before you use a model: they are not this licence, and a
|
|
133
|
+
permission granted here is not a permission granted there.
|
|
134
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# auroraomics
|
|
2
|
+
|
|
3
|
+
Virtual spatial transcriptomics from H&E histology.
|
|
4
|
+
|
|
5
|
+
This package holds the pieces of that pipeline that are pure Python, so the
|
|
6
|
+
same code runs on your laptop, in a GPU container and on the service:
|
|
7
|
+
|
|
8
|
+
- **`auroraomics.qc`** — the three patch-quality predicates (foreground, blur,
|
|
9
|
+
stained tissue) applied to every candidate tile before a model sees it, and
|
|
10
|
+
the short-circuiting cascade that combines them.
|
|
11
|
+
- **`auroraomics.pack`** — build the `patches` archive a prediction takes as
|
|
12
|
+
input (`pack_tiles`), and validate one you have been handed (`read_archive`).
|
|
13
|
+
- **`auroraomics.h5ad`** — write the standard `.h5ad` result with `h5py`
|
|
14
|
+
alone, streaming the expression matrix batch by batch so peak memory is one
|
|
15
|
+
batch rather than the whole matrix.
|
|
16
|
+
- **`auroraomics.subsample`** — pick the densest contiguous square of spots
|
|
17
|
+
when a slide yields more tiles than a run is allowed to spend.
|
|
18
|
+
- **`auroraomics.contracts`** — the shared contract values (container layout,
|
|
19
|
+
input-kind caps, result layout) as data, so nothing here re-types a number
|
|
20
|
+
the service also reads.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
pip install auroraomics
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The core needs only numpy, h5py, OpenCV and Pillow. Extras add the API client
|
|
29
|
+
(`client`), a local model runtime (`deepspotm`) and pyramidal slide reading
|
|
30
|
+
(`slide`).
|
|
31
|
+
|
|
32
|
+
## Pack tiles, then look at the report
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import auroraomics as ao
|
|
36
|
+
|
|
37
|
+
report = ao.pack_tiles(tiles, "sample.zip", mpp=0.499, thumbnail=thumb)
|
|
38
|
+
print(report.written, "tiles kept,", report.rejected, "dropped")
|
|
39
|
+
print(report.rejected_by_reason) # {'foreground_ratio': 12, ...}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`tiles` is any iterable of `ao.Tile(image, x, y)`, where `image` is an RGB
|
|
43
|
+
`uint8` array and `x`/`y` are the tile's top-left position in full-resolution
|
|
44
|
+
pixels. Tiles are quality-checked as they stream past, and only the ones that
|
|
45
|
+
pass are written, so an iterable that reads a slide lazily never has to hold
|
|
46
|
+
more than one tile in memory.
|
|
47
|
+
|
|
48
|
+
## Validate an archive before trusting it
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
archive = ao.read_archive("sample.zip") # raises ArchiveError on anything odd
|
|
52
|
+
for tile in archive.tiles(): # decoded one at a time
|
|
53
|
+
...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`read_archive` checks the member names, the manifest, the tile geometry and the
|
|
57
|
+
declared sizes *before* decoding a single pixel, and refuses an archive whose
|
|
58
|
+
members do not match the container contract.
|
|
59
|
+
|
|
60
|
+
## Write a result
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
ao.write_result(
|
|
64
|
+
"result.h5ad",
|
|
65
|
+
obs=obs, # per-spot columns, as plain arrays
|
|
66
|
+
var=var, # per-gene columns, indexed by gene id
|
|
67
|
+
spatial=coords, # (n_spots, 2) array -> obsm["spatial"]
|
|
68
|
+
x=batches, # an array, or an iterable of row batches
|
|
69
|
+
uns={"model": {"id": "..."}},
|
|
70
|
+
layers={"image_only": other_batches},
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The file reads back as an ordinary `AnnData` in anndata 0.10 and 0.11. Passing
|
|
75
|
+
an iterable for `x` streams it: each batch is compressed into the file as it
|
|
76
|
+
arrives and then dropped, which is what makes a matrix larger than memory
|
|
77
|
+
writable.
|
|
78
|
+
|
|
79
|
+
## Typing
|
|
80
|
+
|
|
81
|
+
The package ships `py.typed`, so annotations are visible to type checkers in
|
|
82
|
+
your project.
|
|
83
|
+
|
|
84
|
+
## Licence
|
|
85
|
+
|
|
86
|
+
The code in this package is licensed under
|
|
87
|
+
[PolyForm Noncommercial 1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0),
|
|
88
|
+
which permits use for any purpose that is not commercial. It is the same licence the
|
|
89
|
+
model package this client is built for carries, so installing both puts you under one
|
|
90
|
+
rule rather than two.
|
|
91
|
+
|
|
92
|
+
The model weights are licensed separately by whoever publishes them, and access to them
|
|
93
|
+
may be gated. Read those terms before you use a model: they are not this licence, and a
|
|
94
|
+
permission granted here is not a permission granted there.
|
|
95
|
+
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "auroraomics"
|
|
7
|
+
version = "0.1.0.dev0"
|
|
8
|
+
description = "Virtual spatial transcriptomics from H&E histology: patch QC, tile packing and the .h5ad result contract."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
# Non-commercial, and the same licence as the model package this client is built
|
|
12
|
+
# for, so a user installing both faces one rule rather than two. PEP 639 forbids
|
|
13
|
+
# a licence CLASSIFIER beside an expression, so this line is the whole
|
|
14
|
+
# declaration; the model weights carry their own separate terms.
|
|
15
|
+
license = "PolyForm-Noncommercial-1.0.0"
|
|
16
|
+
license-files = ["LICENSE"]
|
|
17
|
+
authors = [{ name = "Kalin Nonchev" }]
|
|
18
|
+
keywords = ["histopathology", "spatial-transcriptomics", "h5ad", "anndata", "whole-slide-image"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
25
|
+
"Typing :: Typed",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
# The CORE runtime, and nothing else. These four are what the modules in this
|
|
29
|
+
# distribution actually import at run time, and they are deliberately the set a
|
|
30
|
+
# GPU pipeline image can already satisfy: no torch, no pandas, no anndata, no
|
|
31
|
+
# slide reader. Anything heavier belongs in an extra, so a user who only wants
|
|
32
|
+
# to pack tiles or read a result never pays for a runtime they will not run.
|
|
33
|
+
dependencies = [
|
|
34
|
+
"numpy>=1.23",
|
|
35
|
+
"h5py>=3.9",
|
|
36
|
+
"opencv-python-headless>=4.5",
|
|
37
|
+
"pillow>=9",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
# The API client. Declared here so the install line in the documentation is
|
|
42
|
+
# stable from the first release; the code that imports these lands with it.
|
|
43
|
+
client = ["httpx>=0.27", "pydantic>=2", "anndata>=0.10"]
|
|
44
|
+
# The local model runtime. Intentionally EMPTY, not a guess: pinning a package
|
|
45
|
+
# that nothing in this distribution imports would install weight-bearing
|
|
46
|
+
# dependencies for dead code. The pin arrives in the same change as the
|
|
47
|
+
# runtime that imports it, so `pip install "auroraomics[deepspotm]"` never
|
|
48
|
+
# means something different from what the package can do.
|
|
49
|
+
deepspotm = []
|
|
50
|
+
# Reading pyramidal slide formats, for callers who want this package to cut
|
|
51
|
+
# their tiles rather than handing it tiles they cut themselves.
|
|
52
|
+
slide = ["tifffile>=2023.7.10", "imagecodecs>=2023.3.16"]
|
|
53
|
+
# The test environment. anndata is a TEST dependency on purpose: it is the
|
|
54
|
+
# reader whose behaviour the h5py-only writer is held to, and depending on it
|
|
55
|
+
# at run time would put pandas and its stack into every install.
|
|
56
|
+
#
|
|
57
|
+
# numpy<2 is not a preference. This package is installed into image builds
|
|
58
|
+
# whose compiled stack is ABI-pinned to the numpy 1.x series, so the suite has
|
|
59
|
+
# to pass on the numpy those images resolve — a test matrix that only ever ran
|
|
60
|
+
# on 2.x would go green here and fail where the code actually runs.
|
|
61
|
+
dev = [
|
|
62
|
+
"pytest>=7",
|
|
63
|
+
# setuptools and wheel are TEST dependencies as well as build ones: the
|
|
64
|
+
# release guard builds with --no-isolation so that it needs no network, and
|
|
65
|
+
# a virtual environment on a recent Python ships neither by default. Without
|
|
66
|
+
# them the guard cannot build the thing it is meant to check.
|
|
67
|
+
"setuptools>=77",
|
|
68
|
+
"wheel",
|
|
69
|
+
"anndata>=0.10,<0.12",
|
|
70
|
+
"tifffile>=2023.7.10",
|
|
71
|
+
"imagecodecs>=2023.3.16",
|
|
72
|
+
"build>=1.0",
|
|
73
|
+
"numpy<2",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[tool.setuptools]
|
|
77
|
+
package-dir = { "" = "src" }
|
|
78
|
+
|
|
79
|
+
[tool.setuptools.packages.find]
|
|
80
|
+
where = ["src"]
|
|
81
|
+
|
|
82
|
+
# py.typed makes the annotations visible to a type checker in a consuming
|
|
83
|
+
# project; the vendored contract JSON is data the package reads at import, so
|
|
84
|
+
# both have to be in the wheel. The two glob depths are spelled out rather than
|
|
85
|
+
# using `**`, which older setuptools does not expand in package-data.
|
|
86
|
+
[tool.setuptools.package-data]
|
|
87
|
+
auroraomics = ["py.typed", "_contracts/*.json", "_contracts/*/*.json"]
|
|
88
|
+
|
|
89
|
+
[tool.pytest.ini_options]
|
|
90
|
+
testpaths = ["tests"]
|
|
91
|
+
addopts = "-q --strict-markers"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Virtual spatial transcriptomics from H&E histology.
|
|
2
|
+
|
|
3
|
+
The pieces of that pipeline that are pure Python live here, so the same code
|
|
4
|
+
runs on a laptop, inside a GPU image and on the hosted service:
|
|
5
|
+
|
|
6
|
+
* :mod:`auroraomics.qc` — the three patch-quality predicates and the cascade
|
|
7
|
+
that decides which tiles are worth predicting on.
|
|
8
|
+
* :mod:`auroraomics.pack` — build the ``patches`` archive a prediction takes
|
|
9
|
+
(:func:`pack_tiles`), and validate one before trusting it
|
|
10
|
+
(:func:`read_archive`).
|
|
11
|
+
* :mod:`auroraomics.h5ad` — write the standard result file with ``h5py``
|
|
12
|
+
alone, streaming the matrix so peak memory is one batch.
|
|
13
|
+
* :mod:`auroraomics.subsample` — choose the densest contiguous square when a
|
|
14
|
+
slide yields more tiles than a run may spend.
|
|
15
|
+
* :mod:`auroraomics.contracts` — the shared contract values, as data.
|
|
16
|
+
|
|
17
|
+
Nothing here reaches the network, and nothing here sends anything anywhere.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
23
|
+
|
|
24
|
+
from .h5ad import ResultError, write_result
|
|
25
|
+
from .pack import (
|
|
26
|
+
ArchiveError,
|
|
27
|
+
ArchiveRow,
|
|
28
|
+
PackError,
|
|
29
|
+
PackReport,
|
|
30
|
+
PatchArchive,
|
|
31
|
+
Rejection,
|
|
32
|
+
Tile,
|
|
33
|
+
pack_tiles,
|
|
34
|
+
read_archive,
|
|
35
|
+
)
|
|
36
|
+
from .qc import (
|
|
37
|
+
QcResult,
|
|
38
|
+
QcThresholds,
|
|
39
|
+
blur_filter,
|
|
40
|
+
foreground_mask,
|
|
41
|
+
hsv_filter,
|
|
42
|
+
qc_tile,
|
|
43
|
+
)
|
|
44
|
+
from .subsample import subsample_spatial_square
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
# One source for the version: the installed distribution metadata, which
|
|
48
|
+
# the build fills in from the project file. A string spelled here as well
|
|
49
|
+
# would be the copy that goes stale.
|
|
50
|
+
__version__ = version("auroraomics")
|
|
51
|
+
except PackageNotFoundError: # pragma: no cover - running from a source tree
|
|
52
|
+
__version__ = "0+unknown"
|
|
53
|
+
|
|
54
|
+
__all__ = [
|
|
55
|
+
"ArchiveError",
|
|
56
|
+
"ArchiveRow",
|
|
57
|
+
"PackError",
|
|
58
|
+
"PackReport",
|
|
59
|
+
"PatchArchive",
|
|
60
|
+
"QcResult",
|
|
61
|
+
"QcThresholds",
|
|
62
|
+
"Rejection",
|
|
63
|
+
"ResultError",
|
|
64
|
+
"Tile",
|
|
65
|
+
"__version__",
|
|
66
|
+
"blur_filter",
|
|
67
|
+
"foreground_mask",
|
|
68
|
+
"hsv_filter",
|
|
69
|
+
"pack_tiles",
|
|
70
|
+
"qc_tile",
|
|
71
|
+
"read_archive",
|
|
72
|
+
"subsample_spatial_square",
|
|
73
|
+
"write_result",
|
|
74
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Contract documents vendored into this package, with the sha256 of each. Generated - do not edit by hand.",
|
|
3
|
+
"files": {
|
|
4
|
+
"genes/gene-table.2026-09-05.json": "0dbf97f69b37e4fdb1a13e5c05088c717f8f6cec7fb04c49a4987f8c6495a5c9",
|
|
5
|
+
"public-api-counters.tokens.json": "82544d49ca90897172ad5064daae45008175fc7152b8ead6411b49408df9979d",
|
|
6
|
+
"public-api-input-kinds.tokens.json": "654b45f740485ac6e77bd3fc8fd0e91b7453da38c445b37af460bda280351158",
|
|
7
|
+
"public-api.tokens.json": "a77e48b6aaed8ee4020fbfd99796dbfb6dd818ca6fb01c9e2102b4f4a07a3ce7",
|
|
8
|
+
"public-api/golden-16-tiles.manifest.json": "2d93fbfd2aa4542cc75d0c2dea34f199c6cf87f5123201f952b58de4b7d14094",
|
|
9
|
+
"qc-thresholds.tokens.json": "d65de3c306d75ab6588a3a13fedfe2e562c84e12921ebee08f810cd8b0b9ae47"
|
|
10
|
+
}
|
|
11
|
+
}
|