cellestial 0.49.1__tar.gz → 0.49.2__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 (64) hide show
  1. {cellestial-0.49.1 → cellestial-0.49.2}/PKG-INFO +17 -7
  2. {cellestial-0.49.1 → cellestial-0.49.2}/README.md +5 -5
  3. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/__init__.py +11 -1
  4. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/arrow.py +4 -0
  5. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/utilities.py +2 -2
  6. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/__init__.py +3 -0
  7. cellestial-0.49.2/cellestial/util/markers.py +229 -0
  8. {cellestial-0.49.1 → cellestial-0.49.2}/pyproject.toml +29 -2
  9. {cellestial-0.49.1 → cellestial-0.49.2}/LICENSE +0 -0
  10. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/_version.py +0 -0
  11. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/datasets/__init__.py +0 -0
  12. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/datasets/datasets.py +0 -0
  13. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/frames/__init__.py +0 -0
  14. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/frames/build.py +0 -0
  15. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/frames/operations.py +0 -0
  16. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/__init__.py +0 -0
  17. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/_deferred.py +0 -0
  18. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/bracket.py +0 -0
  19. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/ondata_legend.py +0 -0
  20. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/outline.py +0 -0
  21. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/stream.py +0 -0
  22. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/layers/utilities.py +0 -0
  23. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/__init__.py +0 -0
  24. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/base/__init__.py +0 -0
  25. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/base/base.py +0 -0
  26. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/basic/__init__.py +0 -0
  27. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/basic/bar.py +0 -0
  28. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/basic/scatter.py +0 -0
  29. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/common/__init__.py +0 -0
  30. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/common/xyplot.py +0 -0
  31. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/common/xyplots.py +0 -0
  32. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/__init__.py +0 -0
  33. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/dimensional.py +0 -0
  34. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/distribution.py +0 -0
  35. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/distributions.py +0 -0
  36. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/subdimensional.py +0 -0
  37. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/core/subdimensionals.py +0 -0
  38. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/differential/__init__.py +0 -0
  39. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/differential/markers.py +0 -0
  40. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/differential/utilities.py +0 -0
  41. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/differential/volcano.py +0 -0
  42. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/heatmap/__init__.py +0 -0
  43. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/heatmap/dotplot.py +0 -0
  44. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/heatmap/heatmap.py +0 -0
  45. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/heatmap/stacked_violin.py +0 -0
  46. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/heatmap/utilities.py +0 -0
  47. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/quick/__init__.py +0 -0
  48. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/quick/elbow.py +0 -0
  49. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/quick/highest.py +0 -0
  50. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/single/quick/ridge.py +0 -0
  51. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/spatial/__init__.py +0 -0
  52. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/spatial/spatial.py +0 -0
  53. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/spatial/spatials.py +0 -0
  54. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/spatial/utilities.py +0 -0
  55. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/themes/__init__.py +0 -0
  56. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/themes/_distributions.py +0 -0
  57. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/themes/_heatmaps.py +0 -0
  58. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/themes/_scatters.py +0 -0
  59. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/colors.py +0 -0
  60. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/dendrogram.py +0 -0
  61. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/errors.py +0 -0
  62. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/operations.py +0 -0
  63. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/save.py +0 -0
  64. {cellestial-0.49.1 → cellestial-0.49.2}/cellestial/util/utilities.py +0 -0
@@ -1,17 +1,23 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellestial
3
- Version: 0.49.1
4
- Summary:
3
+ Version: 0.49.2
4
+ Summary: Interactive single-cell and spatial omics visualization library
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
7
+ Keywords: anndata,bioinformatics,data-visualization,lets-plot,polars,single-cell,spatial-omics
7
8
  Author: Zaf4
8
9
  Author-email: zafermolbio@gmail.com
9
10
  Requires-Python: >=3.11,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
10
14
  Classifier: Programming Language :: Python :: 3
11
15
  Classifier: Programming Language :: Python :: 3.11
12
16
  Classifier: Programming Language :: Python :: 3.12
13
17
  Classifier: Programming Language :: Python :: 3.13
14
18
  Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Classifier: Topic :: Scientific/Engineering :: Visualization
15
21
  Provides-Extra: extras
16
22
  Requires-Dist: anndata (>=0.10.8,<1.0)
17
23
  Requires-Dist: lets-plot (>=4.9.0,<5.0.0)
@@ -23,6 +29,10 @@ Requires-Dist: scikit-image (>=0.23.1,<1.0)
23
29
  Requires-Dist: scvelo (>=0.3.3,<0.4.0) ; extra == "extras"
24
30
  Requires-Dist: spatialdata (>=0.7,<1.0)
25
31
  Requires-Dist: tqdm (>=4,<5)
32
+ Project-URL: Documentation, https://cellestial.datavil.org
33
+ Project-URL: Homepage, https://cellestial.datavil.org
34
+ Project-URL: Issues, https://github.com/DataVil/Cellestial/issues
35
+ Project-URL: Repository, https://github.com/DataVil/Cellestial
26
36
  Description-Content-Type: text/markdown
27
37
 
28
38
  # Cellestial
@@ -250,14 +260,14 @@ Cellestial mirrors most of `scanpy.pl` with a few naming shifts:
250
260
  - `groupby` becomes `group_by`, `var_names` becomes `keys`.
251
261
  - Saving is a separate `cl.save(plot, "umap.png")` call.
252
262
 
253
- See the [migration guide](sphinx/migrating_from_scanpy.rst) for a side-by-side mapping.
263
+ See the [migration guide](https://cellestial.datavil.org/migrating_from_scanpy.html) for a side-by-side mapping.
254
264
 
255
265
  ## Documentation
256
266
 
257
- - [Quickstart](sphinx/quickstart.rst) — guided tour of the API.
258
- - [Features](sphinx/features.rst) — tooltips, layers, grids, colors, faceting.
259
- - [API reference](sphinx/API.rst) — every function.
260
- - [Migrating from Scanpy](sphinx/migrating_from_scanpy.rst).
267
+ - [Quickstart](https://cellestial.datavil.org/quickstart.html) — guided tour of the API.
268
+ - [Features](https://cellestial.datavil.org/features.html) — tooltips, layers, grids, colors, faceting.
269
+ - [API reference](https://cellestial.datavil.org/API.html) — every function.
270
+ - [Migrating from Scanpy](https://cellestial.datavil.org/migrating_from_scanpy.html).
261
271
 
262
272
  ## License
263
273
 
@@ -223,14 +223,14 @@ Cellestial mirrors most of `scanpy.pl` with a few naming shifts:
223
223
  - `groupby` becomes `group_by`, `var_names` becomes `keys`.
224
224
  - Saving is a separate `cl.save(plot, "umap.png")` call.
225
225
 
226
- See the [migration guide](sphinx/migrating_from_scanpy.rst) for a side-by-side mapping.
226
+ See the [migration guide](https://cellestial.datavil.org/migrating_from_scanpy.html) for a side-by-side mapping.
227
227
 
228
228
  ## Documentation
229
229
 
230
- - [Quickstart](sphinx/quickstart.rst) — guided tour of the API.
231
- - [Features](sphinx/features.rst) — tooltips, layers, grids, colors, faceting.
232
- - [API reference](sphinx/API.rst) — every function.
233
- - [Migrating from Scanpy](sphinx/migrating_from_scanpy.rst).
230
+ - [Quickstart](https://cellestial.datavil.org/quickstart.html) — guided tour of the API.
231
+ - [Features](https://cellestial.datavil.org/features.html) — tooltips, layers, grids, colors, faceting.
232
+ - [API reference](https://cellestial.datavil.org/API.html) — every function.
233
+ - [Migrating from Scanpy](https://cellestial.datavil.org/migrating_from_scanpy.html).
234
234
 
235
235
  ## License
236
236
 
@@ -37,7 +37,15 @@ from cellestial.single import (
37
37
  xyplots,
38
38
  )
39
39
  from cellestial.spatial import spatial, spatials
40
- from cellestial.util import get_figure, get_figures, get_mapping, retrieve, save
40
+ from cellestial.util import (
41
+ get_figure,
42
+ get_figures,
43
+ get_mapping,
44
+ marker_genes,
45
+ marker_genes_dict,
46
+ retrieve,
47
+ save,
48
+ )
41
49
  from cellestial.util.colors import (
42
50
  BLUE,
43
51
  CHERRY,
@@ -84,6 +92,8 @@ __all__ = [
84
92
  "get_mapping",
85
93
  "heatmap",
86
94
  "highest_expressed_genes",
95
+ "marker_genes",
96
+ "marker_genes_dict",
87
97
  "markers",
88
98
  "matrixplot",
89
99
  "ondata_legend",
@@ -250,6 +250,10 @@ def arrow_axis(
250
250
  MissingAestheticError
251
251
  If `x` or `y` cannot be inferred from the receiving plot.
252
252
 
253
+ Notes
254
+ -----
255
+ Uses `geom_path` to draw the axis lines and `geom_segment` for the arrowheads.
256
+
253
257
  Examples
254
258
  --------
255
259
  Without arrow.
@@ -136,8 +136,8 @@ def _distribution(
136
136
  elif len(keys) > 1 and group_by != variable_column:
137
137
  _warn(
138
138
  f"Multiple keys provided; `group_by={group_by!r}` cannot share the "
139
- f"x-axis with the variable column. Falling back to "
140
- f"`group_by={variable_column!r}`. For a per-key panel, use the plural variant."
139
+ f"x-axis with the variable column.\nFalling back to "
140
+ f"`group_by={variable_column!r}`. For a per-key panel, use the plural variant ({geom}s)."
141
141
  )
142
142
  group_by = variable_column
143
143
 
@@ -2,6 +2,7 @@ from cellestial.util.dendrogram import (
2
2
  _get_dendrogram,
3
3
  _get_dendrogram_path_frame,
4
4
  )
5
+ from cellestial.util.markers import marker_genes, marker_genes_dict
5
6
  from cellestial.util.operations import get_figure, get_figures, get_mapping, retrieve
6
7
  from cellestial.util.save import save
7
8
  from cellestial.util.utilities import (
@@ -43,6 +44,8 @@ __all__ = [
43
44
  "get_figure",
44
45
  "get_figures",
45
46
  "get_mapping",
47
+ "marker_genes",
48
+ "marker_genes_dict",
46
49
  "retrieve",
47
50
  "save",
48
51
  ]
@@ -0,0 +1,229 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Sequence
4
+
5
+ from anndata import AnnData
6
+
7
+ from cellestial.util.errors import KeyNotFoundError, UnsupportedDataTypeError
8
+
9
+
10
+ def _marker_names_per_group(
11
+ data: AnnData,
12
+ groups: Sequence[str] | None,
13
+ *,
14
+ key: str,
15
+ n_genes: int,
16
+ ) -> dict[str, list[str]]:
17
+ """
18
+ Read the top-`n_genes` gene names per group from a precomputed ranking.
19
+
20
+ Shared core for `marker_genes` and `marker_genes_dict`: validates inputs
21
+ and returns one full top-N list per selected group, in group order, with
22
+ no cross-group de-duplication.
23
+ """
24
+ if groups is not None and (not isinstance(groups, Sequence) or isinstance(groups, str)):
25
+ msg = "`groups` must be a Sequence of strings or None"
26
+ raise TypeError(msg)
27
+
28
+ if n_genes < 1:
29
+ msg = f"`n_genes` must be >= 1, got {n_genes}."
30
+ raise ValueError(msg)
31
+
32
+ if isinstance(data, AnnData):
33
+ if key not in data.uns:
34
+ msg = (
35
+ f"`adata.uns[{key!r}]` not found. "
36
+ "Run `scanpy.tl.rank_genes_groups` first "
37
+ "(or pass the correct `key_added` value as `key`)."
38
+ )
39
+ raise KeyNotFoundError(msg)
40
+
41
+ record = data.uns[key]
42
+ if "names" not in record:
43
+ msg = (
44
+ f"`adata.uns[{key!r}]` does not look like a "
45
+ "`rank_genes_groups` result (missing 'names')."
46
+ )
47
+ raise KeyNotFoundError(msg)
48
+
49
+ names = record["names"]
50
+ available_groups = list(names.dtype.names)
51
+
52
+ if groups is None:
53
+ selected = available_groups
54
+ else:
55
+ selected = list(groups)
56
+ unknown = [group for group in selected if group not in available_groups]
57
+ if unknown:
58
+ msg = (
59
+ f"Groups {unknown!r} not found in "
60
+ f"`adata.uns[{key!r}]`. Available: {available_groups!r}."
61
+ )
62
+ raise KeyNotFoundError(msg)
63
+
64
+ n_available = len(names)
65
+ if n_genes > n_available:
66
+ msg = (
67
+ f"`n_genes={n_genes}` exceeds the {n_available} ranked genes "
68
+ f"stored in `adata.uns[{key!r}]`."
69
+ )
70
+ raise ValueError(msg)
71
+
72
+ markers = {group: [str(gene) for gene in names[group][:n_genes]] for group in selected}
73
+ else:
74
+ msg = f"Unsupported data type: `{type(data)}`"
75
+ raise UnsupportedDataTypeError(msg)
76
+
77
+ return markers
78
+
79
+
80
+ def marker_genes(
81
+ data: AnnData,
82
+ groups: Sequence[str] | None = None,
83
+ *,
84
+ key: str = "rank_genes_groups",
85
+ n_genes: int = 5,
86
+ ) -> list[str]:
87
+ """
88
+ Select the top-ranked marker gene names from a precomputed ranking.
89
+
90
+ The returned list is meant to be passed straight into the `keys` argument
91
+ of the dimensional and distribution plots (e.g. `umaps`, `violins`), so
92
+ each marker becomes one panel.
93
+
94
+ Parameters
95
+ ----------
96
+ data : AnnData
97
+ The single-cell data object holding the precomputed differential
98
+ expression ranking.
99
+ groups : Sequence[str] | None, default=None
100
+ Subset of groups to pull markers from, in order. `None` keeps all
101
+ groups in their stored order.
102
+ key : str, default='rank_genes_groups'
103
+ The key under which the precomputed ranking is stored on `data`.
104
+ n_genes : int, default=5
105
+ Number of top genes to pull per group.
106
+
107
+ Returns
108
+ -------
109
+ list[str]
110
+ Flattened, order-preserving list of marker gene names with duplicates
111
+ removed (a gene ranked highly in several groups is kept once, at its
112
+ first occurrence).
113
+
114
+ Raises
115
+ ------
116
+ UnsupportedDataTypeError
117
+ If `data` is not a supported single-cell data object.
118
+ KeyNotFoundError
119
+ If the ranking result or a requested group is missing.
120
+ ValueError
121
+ If `n_genes` is out of range.
122
+ TypeError
123
+ If `groups` is neither a Sequence of strings nor None.
124
+
125
+ Notes
126
+ -----
127
+ Reads only the gene names, not their scores; use `markers` to plot the
128
+ ranking itself. Use `marker_genes_dict` to keep the per-group grouping.
129
+
130
+ Examples
131
+ --------
132
+ Color a UMAP grid by the top markers of a single group.
133
+
134
+ .. jupyter-execute::
135
+
136
+ import scanpy as sc
137
+
138
+ import cellestial as cl
139
+
140
+ data = sc.datasets.pbmc68k_reduced()
141
+
142
+ cl.umaps(data, keys=cl.marker_genes(data, groups=["CD14+ Monocyte"]))
143
+
144
+ Violin the top markers across every group.
145
+
146
+ .. jupyter-execute::
147
+
148
+ cl.violins(data, keys=cl.marker_genes(data, n_genes=3))
149
+ """
150
+ per_group = _marker_names_per_group(data, groups, key=key, n_genes=n_genes)
151
+
152
+ # Flatten group by group, dropping any gene already seen so the list can
153
+ # feed `keys` without producing duplicate panels.
154
+ seen: set[str] = set()
155
+ marker_names: list[str] = []
156
+ for group_names in per_group.values():
157
+ for gene_name in group_names:
158
+ if gene_name in seen:
159
+ continue
160
+ seen.add(gene_name)
161
+ marker_names.append(gene_name)
162
+
163
+ return marker_names
164
+
165
+
166
+ def marker_genes_dict(
167
+ data: AnnData,
168
+ groups: Sequence[str] | None = None,
169
+ *,
170
+ key: str = "rank_genes_groups",
171
+ n_genes: int = 5,
172
+ ) -> dict[str, list[str]]:
173
+ """
174
+ Select the top-ranked marker gene names per group from a precomputed ranking.
175
+
176
+ Like `marker_genes`, but keeps the grouping: each group maps to its own
177
+ full top-`n_genes` list.
178
+
179
+ Parameters
180
+ ----------
181
+ data : AnnData
182
+ The single-cell data object holding the precomputed differential
183
+ expression ranking.
184
+ groups : Sequence[str] | None, default=None
185
+ Subset of groups to pull markers from, in order. `None` keeps all
186
+ groups in their stored order.
187
+ key : str, default='rank_genes_groups'
188
+ The key under which the precomputed ranking is stored on `data`.
189
+ n_genes : int, default=5
190
+ Number of top genes to pull per group.
191
+
192
+ Returns
193
+ -------
194
+ dict[str, list[str]]
195
+ Mapping from group label to its top-`n_genes` gene names, in group
196
+ order. Each list is complete; a gene that ranks highly in several
197
+ groups appears under each of them.
198
+
199
+ Raises
200
+ ------
201
+ UnsupportedDataTypeError
202
+ If `data` is not a supported single-cell data object.
203
+ KeyNotFoundError
204
+ If the ranking result or a requested group is missing.
205
+ ValueError
206
+ If `n_genes` is out of range.
207
+ TypeError
208
+ If `groups` is neither a Sequence of strings nor None.
209
+
210
+ Notes
211
+ -----
212
+ Reads only the gene names, not their scores; use `markers` to plot the
213
+ ranking itself. Use `marker_genes` for a flat, de-duplicated list.
214
+
215
+ Examples
216
+ --------
217
+ Inspect the top markers of each group.
218
+
219
+ .. jupyter-execute::
220
+
221
+ import scanpy as sc
222
+
223
+ import cellestial as cl
224
+
225
+ data = sc.datasets.pbmc68k_reduced()
226
+
227
+ cl.marker_genes_dict(data, n_genes=3)
228
+ """
229
+ return _marker_names_per_group(data, groups, key=key, n_genes=n_genes)
@@ -1,13 +1,34 @@
1
1
  [project]
2
2
  name = "cellestial"
3
- version = "0.49.1"
4
- description = ""
3
+ version = "0.49.2"
4
+ description = "Interactive single-cell and spatial omics visualization library"
5
5
  authors = [
6
6
  { name = "Zaf4", email = "zafermolbio@gmail.com" },
7
7
  ]
8
8
  readme = "README.md"
9
9
  license = "Apache-2.0"
10
10
  requires-python = ">=3.11,<4.0"
11
+ keywords = [
12
+ "anndata",
13
+ "bioinformatics",
14
+ "data-visualization",
15
+ "lets-plot",
16
+ "polars",
17
+ "single-cell",
18
+ "spatial-omics",
19
+ ]
20
+ classifiers = [
21
+ "Development Status :: 4 - Beta",
22
+ "Intended Audience :: Science/Research",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Programming Language :: Python :: 3.14",
29
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
30
+ "Topic :: Scientific/Engineering :: Visualization",
31
+ ]
11
32
  dependencies = [
12
33
  "anndata>=0.10.8,<1.0",
13
34
  "lets-plot>=4.9.0,<5.0.0",
@@ -17,6 +38,12 @@ dependencies = [
17
38
  "tqdm>=4,<5",
18
39
  ]
19
40
 
41
+ [project.urls]
42
+ Documentation = "https://cellestial.datavil.org"
43
+ Homepage = "https://cellestial.datavil.org"
44
+ Repository = "https://github.com/DataVil/Cellestial"
45
+ Issues = "https://github.com/DataVil/Cellestial/issues"
46
+
20
47
  [project.optional-dependencies]
21
48
  extras = [
22
49
  "matplotlib>=3.9,<4.0",
File without changes