vima-spatial 0.2.2__tar.gz → 0.2.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 (44) hide show
  1. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/PKG-INFO +5 -2
  2. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/README.md +4 -1
  3. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/pyproject.toml +4 -0
  4. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/setup.cfg +1 -1
  5. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/__init__.py +7 -4
  6. vima_spatial-0.2.4/src/vima/_settings.py +200 -0
  7. vima_spatial-0.2.4/src/vima/cc.py +467 -0
  8. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/data/__init__.py +1 -0
  9. vima_spatial-0.2.4/src/vima/data/download.py +62 -0
  10. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/data/patchcollection.py +126 -27
  11. vima_spatial-0.2.4/src/vima/data/samples.py +87 -0
  12. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/fingerprints.py +95 -6
  13. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/ingest/dimreduce.py +96 -25
  14. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/ingest/ingest.py +124 -21
  15. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/ingest/nonst.py +80 -12
  16. vima_spatial-0.2.4/src/vima/ingest/st.py +354 -0
  17. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/ingest/util.py +21 -4
  18. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/__init__.py +23 -0
  19. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/simple_vae.py +3 -0
  20. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/vae.py +19 -0
  21. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/patchfeatures.py +109 -63
  22. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/train/logging.py +3 -0
  23. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/train/training.py +119 -10
  24. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/features.py +46 -32
  25. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/patches.py +134 -65
  26. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/spatial.py +71 -4
  27. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/umaps.py +16 -0
  28. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima_spatial.egg-info/PKG-INFO +5 -2
  29. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima_spatial.egg-info/SOURCES.txt +4 -2
  30. vima_spatial-0.2.4/tests/test_ra_regression.py +69 -0
  31. vima_spatial-0.2.2/MANIFEST.in +0 -1
  32. vima_spatial-0.2.2/src/vima/cc.py +0 -199
  33. vima_spatial-0.2.2/src/vima/data/samples.py +0 -43
  34. vima_spatial-0.2.2/src/vima/ingest/st.py +0 -227
  35. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/ingest/__init__.py +0 -0
  36. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/resnet_vae.py +0 -0
  37. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/resnetlight_decoder.py +0 -0
  38. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/models/resnetlight_encoder.py +0 -0
  39. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/train/__init__.py +0 -0
  40. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/__init__.py +0 -0
  41. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima/vis/patchexamples.py +0 -0
  42. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima_spatial.egg-info/dependency_links.txt +0 -0
  43. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima_spatial.egg-info/requires.txt +0 -0
  44. {vima_spatial-0.2.2 → vima_spatial-0.2.4}/src/vima_spatial.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vima-spatial
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: variational inference-based microniche analysis
5
5
  Home-page: https://github.com/yakirr/vima
6
6
  Author: Yakir Reshef
@@ -39,9 +39,12 @@ Variational inference-based microniche analysis is a method for conducting case-
39
39
  ```
40
40
  pip install vima-spatial
41
41
  ```
42
+ Note that `vima` requires `pytorch` and `harmonypy`. These should install automatically through `pip`, but if you have trouble, try installing them first, verifying that they work, and then installing `vima`.
42
43
 
43
44
  ## demo
44
- Take a look at our [demo](https://github.com/yakirr/vima/blob/main/demo/demo_IF.ipynb) to see how to get started with an example analysis. We plan to put up demos for other data modalities in the future.
45
+ To get started with an example analysis on a toy spatial transcriptomics dataset, take a look at our brief demo. You can see a [completed read-only version](https://github.com/yakirr/vima/blob/main/demo/demo_ST_minimal.ipynb) or run an [interactive version](https://colab.research.google.com/github/yakirr/tpae/blob/main/demo/demo_ST_minimal.ipynb) yourself on a Google Colab GPU (though this requires Colab Pro due to insufficient memory provided on the free tier.)
46
+
47
+ To see how to apply `vima` to a stain-based modality like CODEX, immunohistochemistry, or immunofluorescence, look at our [immunofluorescence demo](https://github.com/yakirr/vima/blob/main/demo/demo_IF.ipynb).
45
48
 
46
49
  ## citation
47
50
  If you use `vima`, please cite:
@@ -6,9 +6,12 @@ Variational inference-based microniche analysis is a method for conducting case-
6
6
  ```
7
7
  pip install vima-spatial
8
8
  ```
9
+ Note that `vima` requires `pytorch` and `harmonypy`. These should install automatically through `pip`, but if you have trouble, try installing them first, verifying that they work, and then installing `vima`.
9
10
 
10
11
  ## demo
11
- Take a look at our [demo](https://github.com/yakirr/vima/blob/main/demo/demo_IF.ipynb) to see how to get started with an example analysis. We plan to put up demos for other data modalities in the future.
12
+ To get started with an example analysis on a toy spatial transcriptomics dataset, take a look at our brief demo. You can see a [completed read-only version](https://github.com/yakirr/vima/blob/main/demo/demo_ST_minimal.ipynb) or run an [interactive version](https://colab.research.google.com/github/yakirr/tpae/blob/main/demo/demo_ST_minimal.ipynb) yourself on a Google Colab GPU (though this requires Colab Pro due to insufficient memory provided on the free tier.)
13
+
14
+ To see how to apply `vima` to a stain-based modality like CODEX, immunohistochemistry, or immunofluorescence, look at our [immunofluorescence demo](https://github.com/yakirr/vima/blob/main/demo/demo_IF.ipynb).
12
15
 
13
16
  ## citation
14
17
  If you use `vima`, please cite:
@@ -4,3 +4,7 @@ requires = [
4
4
  "wheel"
5
5
  ]
6
6
  build-backend = "setuptools.build_meta"
7
+
8
+ [tool.pytest.ini_options]
9
+ testpaths = ["tests"]
10
+ addopts = "-v"
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = vima-spatial
3
- version = 0.2.2
3
+ version = 0.2.4
4
4
  author = Yakir Reshef
5
5
  author_email = yreshef@broadinstitute.org
6
6
  description = variational inference-based microniche analysis
@@ -1,3 +1,4 @@
1
+ from ._settings import settings, Verbosity
1
2
  from . import data as d
2
3
  from . import cc
3
4
  from . import train as t
@@ -7,12 +8,14 @@ from . import models
7
8
 
8
9
  from .data.patchcollection import PatchCollection
9
10
  from .data.samples import read_samples, reindex_by_sid
11
+ from .data.download import download_zenodo
10
12
  from .train.training import train, fit, set_seed
11
- from .cc import latentreps, association
13
+ from .cc import latentreps, association, compute_mams
12
14
  from .fingerprints import Fingerprints
13
15
  from .patchfeatures import cell_type_counts, expression_profiles, test_features
14
16
 
15
- __all__ = ['d', 'cc', 't', 'pp', 'v', 'models',
16
- 'PatchCollection', 'read_samples', 'reindex_by_sid',
17
- 'train', 'fit', 'set_seed', 'latentreps', 'association',
17
+ __all__ = ['settings', 'Verbosity',
18
+ 'd', 'cc', 't', 'pp', 'v', 'models',
19
+ 'PatchCollection', 'read_samples', 'reindex_by_sid', 'download_zenodo',
20
+ 'train', 'fit', 'set_seed', 'latentreps', 'association', 'compute_mams',
18
21
  'Fingerprints', 'cc', 'cell_type_counts', 'expression_profiles', 'test_features']
@@ -0,0 +1,200 @@
1
+ """Unified output control for vima.
2
+
3
+ All informational output in the package flows through a single ``logging``
4
+ logger (``vima._settings.logger``, named ``"vima"``) and a single progress-bar
5
+ helper (``settings.progress``). User-facing controls live on the module-level
6
+ ``settings`` object, exposed as ``vima.settings``.
7
+
8
+ Three independent knobs:
9
+
10
+ * ``settings.verbosity`` -- how much informational output to emit. Three levels:
11
+
12
+ ================== === ================ ==================================
13
+ name int logging level what is shown
14
+ ================== === ================ ==================================
15
+ ``"minimal"`` 0 ``WARNING`` warnings/errors, progress bars,
16
+ and results only (e.g. the
17
+ ``association`` p-value)
18
+ ``"default"`` 1 ``INFO`` + high-level progress messages
19
+ ``"verbose"`` 2 ``DEBUG`` + detailed diagnostics
20
+ ================== === ================ ==================================
21
+
22
+ * ``settings.diagnostic_plots`` -- how many diagnostic plots to draw, on the same
23
+ three-level scale as ``verbosity``: ``"minimal"`` draws none, ``"default"`` draws
24
+ the plots historically shown by default (QC, mean-variance, embeddings), and
25
+ ``"verbose"`` additionally draws the more detailed plots. Until it is set
26
+ explicitly, it *tracks* ``verbosity`` -- so setting ``verbosity`` alone also
27
+ controls the plots; assigning ``diagnostic_plots`` decouples the two.
28
+
29
+ * ``settings.progress_bars`` -- whether tqdm progress bars are shown. Orthogonal
30
+ to verbosity (bars stay on even at ``"minimal"``); set ``False`` for batch or
31
+ cluster runs.
32
+
33
+ Guidelines for package code:
34
+
35
+ * ``logger.info(...)`` -- normal progress messages (visible at ``default``).
36
+ * ``logger.debug(...)`` -- detailed diagnostics (visible only at ``verbose``).
37
+ * ``logger.warning(...)`` -- warnings the user should see at every level.
38
+ * ``settings.result(...)`` -- user-facing results shown at every level.
39
+ * ``settings.progress(iterable, name=...)`` -- wrap any loop needing a bar.
40
+ * ``if settings.show_plots(...):`` -- guard a diagnostic plot. Pass ``"verbose"``
41
+ for the detailed plots; the default level guards the standard ones.
42
+ """
43
+
44
+ import sys
45
+ import logging
46
+ from enum import IntEnum
47
+
48
+ from tqdm.auto import tqdm
49
+
50
+ __all__ = ["Verbosity", "settings", "logger"]
51
+
52
+
53
+ class Verbosity(IntEnum):
54
+ """Amount of informational output emitted by vima."""
55
+
56
+ minimal = 0 # warnings + progress bars + results only
57
+ default = 1 # + high-level info messages (the historical default)
58
+ verbose = 2 # + detailed diagnostics
59
+
60
+ @classmethod
61
+ def parse(cls, value):
62
+ """Coerce an int, name string, or Verbosity into a Verbosity."""
63
+ if isinstance(value, cls):
64
+ return value
65
+ if isinstance(value, str):
66
+ try:
67
+ return cls[value]
68
+ except KeyError:
69
+ raise ValueError(
70
+ f"unknown verbosity {value!r}; "
71
+ f"expected one of {[v.name for v in cls]} or 0/1/2"
72
+ )
73
+ return cls(value)
74
+
75
+
76
+ _LOGGING_LEVELS = {
77
+ Verbosity.minimal: logging.WARNING,
78
+ Verbosity.default: logging.INFO,
79
+ Verbosity.verbose: logging.DEBUG,
80
+ }
81
+
82
+ logger = logging.getLogger("vima")
83
+
84
+ # ANSI colors: debug messages are grayed out, results are green.
85
+ _GRAY, _GREEN, _RESET = "\033[90m", "\033[32m", "\033[0m"
86
+
87
+
88
+ class _ColorFormatter(logging.Formatter):
89
+ """Format log records, graying out DEBUG-level messages."""
90
+
91
+ def format(self, record):
92
+ msg = super().format(record)
93
+ if record.levelno == logging.DEBUG:
94
+ return f"{_GRAY}{msg}{_RESET}"
95
+ return msg
96
+
97
+
98
+ class _TqdmLoggingHandler(logging.StreamHandler):
99
+ """Route log records through ``tqdm.write`` so they never corrupt an active
100
+ progress bar. When no bar is live, ``tqdm.write`` degrades to a plain write
101
+ to the stream, so logging in loops without a bar is unaffected. This keeps
102
+ the two output channels fully decoupled: progress bars honor
103
+ ``settings.progress_bars`` and log messages honor ``settings.verbosity``,
104
+ independent of each other.
105
+ """
106
+
107
+ def emit(self, record):
108
+ try:
109
+ msg = self.format(record)
110
+ tqdm.write(msg, file=self.stream, end=self.terminator)
111
+ except Exception:
112
+ self.handleError(record)
113
+
114
+
115
+ class Settings:
116
+ """Global vima output settings; access via the ``vima.settings`` singleton."""
117
+
118
+ def __init__(self):
119
+ # Attach a single stdout handler and keep our records off the root
120
+ # logger so vima's output is independent of any host logging config.
121
+ # The "vima" logger is a process-global singleton that survives module
122
+ # reloads, so clear any handler we previously attached before adding a
123
+ # new one; otherwise re-importing vima (e.g. importlib.reload in a
124
+ # notebook) accumulates handlers and every message prints N times.
125
+ # Match by class *name*, not isinstance: each reload defines a fresh
126
+ # _TqdmLoggingHandler class, so handlers left by earlier reloads are
127
+ # instances of a different (stale) class object and would fail an
128
+ # isinstance check against the current class.
129
+ for h in list(logger.handlers):
130
+ if type(h).__name__ == "_TqdmLoggingHandler":
131
+ logger.removeHandler(h)
132
+ handler = _TqdmLoggingHandler(sys.stdout)
133
+ handler.setFormatter(_ColorFormatter("%(message)s"))
134
+ logger.addHandler(handler)
135
+ logger.propagate = False
136
+
137
+ self.progress_bars = True
138
+ self._verbosity = None
139
+ # ``diagnostic_plots`` tracks ``verbosity`` until the user sets it.
140
+ self._diagnostic_plots = None
141
+ self._diagnostic_plots_explicit = False
142
+ self.verbosity = Verbosity.default
143
+
144
+ @property
145
+ def verbosity(self):
146
+ """Current :class:`Verbosity` level (see module docstring)."""
147
+ return self._verbosity
148
+
149
+ @verbosity.setter
150
+ def verbosity(self, value):
151
+ self._verbosity = Verbosity.parse(value)
152
+ logger.setLevel(_LOGGING_LEVELS[self._verbosity])
153
+ if not self._diagnostic_plots_explicit:
154
+ self._diagnostic_plots = self._verbosity
155
+
156
+ @property
157
+ def diagnostic_plots(self):
158
+ """:class:`Verbosity` level controlling how many diagnostic plots are drawn.
159
+
160
+ Tracks :attr:`verbosity` until assigned; assigning it decouples the two.
161
+ """
162
+ return self._diagnostic_plots
163
+
164
+ @diagnostic_plots.setter
165
+ def diagnostic_plots(self, value):
166
+ self._diagnostic_plots = Verbosity.parse(value)
167
+ self._diagnostic_plots_explicit = True
168
+
169
+ def show_plots(self, level=Verbosity.default):
170
+ """Whether diagnostic plots at ``level`` should be drawn.
171
+
172
+ ``level`` is anything :meth:`Verbosity.parse` accepts (default the
173
+ standard-plot level); pass ``"verbose"`` for the more detailed plots.
174
+ """
175
+ return self._diagnostic_plots >= Verbosity.parse(level)
176
+
177
+ def progress(self, iterable=None, name=None, total=None, ncols=100, desc=None, **kwargs):
178
+ """tqdm wrapper honoring ``settings.progress_bars``.
179
+
180
+ Central replacement for the per-module ``pb = lambda ...`` helpers.
181
+ ``name`` is a brief label for the loop, shown as the tqdm ``desc``
182
+ prefix (``desc`` is still accepted as an alias; ``name`` wins).
183
+ """
184
+ using_widget = any(
185
+ cls.__module__ == "tqdm.notebook"
186
+ for cls in tqdm.mro()
187
+ )
188
+ return tqdm(
189
+ iterable, desc=name if name is not None else desc, total=total,
190
+ ncols=ncols * (7 if using_widget else 1),
191
+ bar_format='{l_bar}{bar}{r_bar}',
192
+ disable=not self.progress_bars, **kwargs,
193
+ )
194
+
195
+ def result(self, message):
196
+ """Emit a user-facing result, shown at every verbosity level."""
197
+ tqdm.write(f"{_GREEN}{message}{_RESET}", file=sys.stdout)
198
+
199
+
200
+ settings = Settings()