ggnomics 0.1.1__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.
- ggnomics-0.1.1/.gitignore +74 -0
- ggnomics-0.1.1/API_STABILIZATION_PLAN.md +363 -0
- ggnomics-0.1.1/AUTHORS.md +27 -0
- ggnomics-0.1.1/CHANGELOG.md +73 -0
- ggnomics-0.1.1/CODE_OF_CONDUCT.md +84 -0
- ggnomics-0.1.1/CONTRIBUTING.md +332 -0
- ggnomics-0.1.1/LICENSE +21 -0
- ggnomics-0.1.1/MANIFEST.in +39 -0
- ggnomics-0.1.1/PKG-INFO +302 -0
- ggnomics-0.1.1/README.md +203 -0
- ggnomics-0.1.1/examples/00_mock_data.py +449 -0
- ggnomics-0.1.1/ggnomics/__init__.py +175 -0
- ggnomics-0.1.1/ggnomics/_backends/__init__.py +35 -0
- ggnomics-0.1.1/ggnomics/_backends/_bioc.py +54 -0
- ggnomics-0.1.1/ggnomics/_backends/anndata.py +632 -0
- ggnomics-0.1.1/ggnomics/_backends/mudata.py +206 -0
- ggnomics-0.1.1/ggnomics/_backends/singlecellexperiment.py +689 -0
- ggnomics-0.1.1/ggnomics/_backends/summarizedexperiment.py +454 -0
- ggnomics-0.1.1/ggnomics/_compose.py +153 -0
- ggnomics-0.1.1/ggnomics/_utils.py +231 -0
- ggnomics-0.1.1/ggnomics/_version.py +24 -0
- ggnomics-0.1.1/ggnomics/abundance.py +104 -0
- ggnomics-0.1.1/ggnomics/bulk/__init__.py +1 -0
- ggnomics-0.1.1/ggnomics/bulk/pca.py +131 -0
- ggnomics-0.1.1/ggnomics/coldata.py +223 -0
- ggnomics-0.1.1/ggnomics/composition.py +45 -0
- ggnomics-0.1.1/ggnomics/de_plots.py +363 -0
- ggnomics-0.1.1/ggnomics/dotplot.py +114 -0
- ggnomics-0.1.1/ggnomics/expression.py +469 -0
- ggnomics-0.1.1/ggnomics/heatmap.py +77 -0
- ggnomics-0.1.1/ggnomics/highest_exprs.py +247 -0
- ggnomics-0.1.1/ggnomics/multimodal.py +323 -0
- ggnomics-0.1.1/ggnomics/pairs.py +168 -0
- ggnomics-0.1.1/ggnomics/palettes.py +392 -0
- ggnomics-0.1.1/ggnomics/pca/__init__.py +2 -0
- ggnomics-0.1.1/ggnomics/pca/methods.py +50 -0
- ggnomics-0.1.1/ggnomics/pca/result.py +34 -0
- ggnomics-0.1.1/ggnomics/pseudobulk.py +477 -0
- ggnomics-0.1.1/ggnomics/qc.py +59 -0
- ggnomics-0.1.1/ggnomics/reduced_dim.py +19 -0
- ggnomics-0.1.1/ggnomics/repertoire.py +489 -0
- ggnomics-0.1.1/ggnomics/ridge.py +81 -0
- ggnomics-0.1.1/ggnomics/scatter.py +437 -0
- ggnomics-0.1.1/ggnomics/signif/__init__.py +13 -0
- ggnomics-0.1.1/ggnomics/signif/_brackets.py +136 -0
- ggnomics-0.1.1/ggnomics/signif/_geom.py +327 -0
- ggnomics-0.1.1/ggnomics/signif/_stats.py +130 -0
- ggnomics-0.1.1/ggnomics/singlecell/__init__.py +2 -0
- ggnomics-0.1.1/ggnomics/singlecell/pca.py +113 -0
- ggnomics-0.1.1/ggnomics/singlecell/umap.py +64 -0
- ggnomics-0.1.1/ggnomics/stats_plots.py +692 -0
- ggnomics-0.1.1/ggnomics/upset/README.md +59 -0
- ggnomics-0.1.1/ggnomics/upset/THIRD-PARTY-NOTICES-upset.md +30 -0
- ggnomics-0.1.1/ggnomics/upset/__init__.py +127 -0
- ggnomics-0.1.1/ggnomics/upset/_types.py +185 -0
- ggnomics-0.1.1/ggnomics/upset/_utils_query.py +67 -0
- ggnomics-0.1.1/ggnomics/upset/_utils_theme.py +22 -0
- ggnomics-0.1.1/ggnomics/upset/alignment.py +229 -0
- ggnomics-0.1.1/ggnomics/upset/annotations.py +387 -0
- ggnomics-0.1.1/ggnomics/upset/examples.py +22 -0
- ggnomics-0.1.1/ggnomics/upset/intersections.py +569 -0
- ggnomics-0.1.1/ggnomics/upset/matrix.py +189 -0
- ggnomics-0.1.1/ggnomics/upset/modes.py +129 -0
- ggnomics-0.1.1/ggnomics/upset/plot.py +267 -0
- ggnomics-0.1.1/ggnomics/upset/queries.py +40 -0
- ggnomics-0.1.1/ggnomics/upset/set_size.py +88 -0
- ggnomics-0.1.1/ggnomics/upset/stripes.py +40 -0
- ggnomics-0.1.1/ggnomics/upset/testing.py +213 -0
- ggnomics-0.1.1/ggnomics/upset/themes.py +80 -0
- ggnomics-0.1.1/ggnomics/upset/venn.py +372 -0
- ggnomics-0.1.1/ggnomics/violin.py +159 -0
- ggnomics-0.1.1/ggnomics/volcano.py +71 -0
- ggnomics-0.1.1/ggnomics.egg-info/PKG-INFO +302 -0
- ggnomics-0.1.1/ggnomics.egg-info/SOURCES.txt +108 -0
- ggnomics-0.1.1/ggnomics.egg-info/dependency_links.txt +1 -0
- ggnomics-0.1.1/ggnomics.egg-info/requires.txt +85 -0
- ggnomics-0.1.1/ggnomics.egg-info/scm_file_list.json +265 -0
- ggnomics-0.1.1/ggnomics.egg-info/scm_version.json +8 -0
- ggnomics-0.1.1/ggnomics.egg-info/top_level.txt +1 -0
- ggnomics-0.1.1/great-docs.yml +847 -0
- ggnomics-0.1.1/pyproject.toml +270 -0
- ggnomics-0.1.1/setup.cfg +4 -0
- ggnomics-0.1.1/tests/conftest.py +128 -0
- ggnomics-0.1.1/tests/test_abundance.py +52 -0
- ggnomics-0.1.1/tests/test_backends.py +224 -0
- ggnomics-0.1.1/tests/test_coldata.py +82 -0
- ggnomics-0.1.1/tests/test_compose.py +196 -0
- ggnomics-0.1.1/tests/test_de_plots.py +145 -0
- ggnomics-0.1.1/tests/test_default_palette.py +230 -0
- ggnomics-0.1.1/tests/test_edge_cases.py +110 -0
- ggnomics-0.1.1/tests/test_expression.py +236 -0
- ggnomics-0.1.1/tests/test_heatmap.py +48 -0
- ggnomics-0.1.1/tests/test_highest_exprs.py +106 -0
- ggnomics-0.1.1/tests/test_multimodal.py +319 -0
- ggnomics-0.1.1/tests/test_pairs.py +56 -0
- ggnomics-0.1.1/tests/test_palettes.py +161 -0
- ggnomics-0.1.1/tests/test_plotting.py +74 -0
- ggnomics-0.1.1/tests/test_pseudobulk.py +264 -0
- ggnomics-0.1.1/tests/test_public_api_contract.py +205 -0
- ggnomics-0.1.1/tests/test_reduced_dim.py +143 -0
- ggnomics-0.1.1/tests/test_repertoire.py +195 -0
- ggnomics-0.1.1/tests/test_scatter.py +282 -0
- ggnomics-0.1.1/tests/test_signif.py +533 -0
- ggnomics-0.1.1/tests/test_stats_plots.py +295 -0
- ggnomics-0.1.1/tests/test_upset_api.py +142 -0
- ggnomics-0.1.1/tests/test_upset_components.py +419 -0
- ggnomics-0.1.1/tests/test_upset_intersections.py +435 -0
- ggnomics-0.1.1/tests/test_upset_plot.py +270 -0
- ggnomics-0.1.1/tests/test_upset_statistics.py +275 -0
- ggnomics-0.1.1/tests/test_upset_venn.py +262 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# --- Python ---------------------------------------------------------------
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# --- Packaging / build ----------------------------------------------------
|
|
8
|
+
# Written by setuptools_scm at build time from the git tag. Generated, never
|
|
9
|
+
# edited or committed.
|
|
10
|
+
ggnomics/_version.py
|
|
11
|
+
build/
|
|
12
|
+
dist/
|
|
13
|
+
sdist/
|
|
14
|
+
wheels/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
*.egg
|
|
17
|
+
*.whl
|
|
18
|
+
*.tar.gz
|
|
19
|
+
MANIFEST
|
|
20
|
+
|
|
21
|
+
# --- Testing / coverage ---------------------------------------------------
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.cache/
|
|
24
|
+
.coverage
|
|
25
|
+
.coverage.*
|
|
26
|
+
coverage.xml
|
|
27
|
+
htmlcov/
|
|
28
|
+
nosetests.xml
|
|
29
|
+
|
|
30
|
+
# --- Linting / type checking ----------------------------------------------
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
.mypy_cache/
|
|
33
|
+
|
|
34
|
+
# --- tox / virtual environments -------------------------------------------
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
.venv/
|
|
38
|
+
venv/
|
|
39
|
+
env/
|
|
40
|
+
ENV/
|
|
41
|
+
|
|
42
|
+
# --- Documentation --------------------------------------------------------
|
|
43
|
+
# Legacy MkDocs output (MkDocs is no longer the site renderer).
|
|
44
|
+
/site/
|
|
45
|
+
|
|
46
|
+
# Retired documentation systems (Sphinx + quartodoc/Quarto), superseded by
|
|
47
|
+
# great-docs. Kept on disk, prefixed with __old_, and excluded from version
|
|
48
|
+
# control rather than deleted outright.
|
|
49
|
+
_old_docs/
|
|
50
|
+
__old_docs/
|
|
51
|
+
__old_vignettes/
|
|
52
|
+
__old_readthedocs.yml
|
|
53
|
+
.github/workflows/__old_docs.yml
|
|
54
|
+
.github/workflows/__old_publish-docs.yml
|
|
55
|
+
.github/workflows/__old_readme_plots.yml
|
|
56
|
+
tools/__old_build_tutorial_notebooks.py
|
|
57
|
+
|
|
58
|
+
# --- Editors and OS -------------------------------------------------------
|
|
59
|
+
.vscode/
|
|
60
|
+
.idea/
|
|
61
|
+
*.swp
|
|
62
|
+
*.swo
|
|
63
|
+
*~
|
|
64
|
+
.DS_Store
|
|
65
|
+
Thumbs.db
|
|
66
|
+
|
|
67
|
+
# Great Docs build directory (ephemeral, do not commit)
|
|
68
|
+
great-docs/
|
|
69
|
+
|
|
70
|
+
# Great Docs versioned-build artifacts
|
|
71
|
+
_great_docs_build/
|
|
72
|
+
.great-docs-build/
|
|
73
|
+
.great-docs-cache/
|
|
74
|
+
.great-docs/
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# ggnomics API stabilization plan
|
|
2
|
+
|
|
3
|
+
*Status: discussion draft. Written from a full read-through of `ggnomics/` (~11.6k lines)
|
|
4
|
+
on 2026-08-21, ahead of committing to a stable public API.*
|
|
5
|
+
|
|
6
|
+
## 1. Why this document
|
|
7
|
+
|
|
8
|
+
`ggnomics` already has a working, well-tested architecture: a `singledispatch` generic
|
|
9
|
+
per plot family, a canonical `pandas.DataFrame` implementation, and lazily-registered
|
|
10
|
+
adapters for `AnnData`, `SingleCellExperiment`, `SummarizedExperiment`, and `MuData`
|
|
11
|
+
(`tests/test_public_api_contract.py` pins this contract — return types, non-mutation,
|
|
12
|
+
error messages). That pattern is the right foundation and does not need to change.
|
|
13
|
+
|
|
14
|
+
What's *not* settled is the **naming and grouping of the ~50 public functions built on
|
|
15
|
+
top of it** — which verb/noun a user reaches for, which names are aliases of which,
|
|
16
|
+
and where the boundary sits between "plot", "compute", and "legacy". This document is
|
|
17
|
+
an inventory of the current state, the specific inconsistencies that will bite users
|
|
18
|
+
once the API is declared stable, and concrete proposals for resolving them.
|
|
19
|
+
|
|
20
|
+
Nothing here is a decision — several sections end with an explicit choice for you to
|
|
21
|
+
make.
|
|
22
|
+
|
|
23
|
+
## 2. The architecture that already works (keep this)
|
|
24
|
+
|
|
25
|
+
Every modern plot function follows the same three-to-four layer shape:
|
|
26
|
+
|
|
27
|
+
1. **Private plotnine builder** — pure geometry from an already-tidy `DataFrame`, no
|
|
28
|
+
data extraction (e.g. `_scatter_ggplot`, `_build_adt_qc_plot`,
|
|
29
|
+
`_build_highest_exprs_plot`). Independently testable, reused across containers.
|
|
30
|
+
2. **Public `@singledispatch` generic**, registered for `pd.DataFrame` — this is the
|
|
31
|
+
canonical implementation and "the interface". It validates columns, builds the tidy
|
|
32
|
+
frame, and calls layer 1. Its docstring is the one source of truth for the
|
|
33
|
+
function's contract.
|
|
34
|
+
3. **Container adapters** in `ggnomics/_backends/{anndata,singlecellexperiment,summarizedexperiment,mudata}.py`
|
|
35
|
+
— extract a `DataFrame` slice from the container (sparse-aware, only densifying the
|
|
36
|
+
requested columns) and re-dispatch to layer 2. Registered only if the optional
|
|
37
|
+
package is importable (`_backends/__init__.py`).
|
|
38
|
+
4. **Convenience wrappers** on top of a layer-2/3 generic, for a fixed common case
|
|
39
|
+
(e.g. `plot_umap(data, ...)` = `plot_embedding(data, dimred="X_umap", ...)`).
|
|
40
|
+
|
|
41
|
+
This gives every function in the "modern" set: one docstring, one error-message
|
|
42
|
+
convention (`TypeError` naming the type + remedy, `KeyError` listing available
|
|
43
|
+
columns), one non-mutation guarantee, and free multi-container support. **This is the
|
|
44
|
+
part of the API that should be declared stable as-is** — the problem is entirely in
|
|
45
|
+
the layer above it (which names exist, what they're called, what they alias).
|
|
46
|
+
|
|
47
|
+
## 3. Two generations of API currently coexist
|
|
48
|
+
|
|
49
|
+
`ggnomics/__init__.py` explicitly separates them, but both ship in the same
|
|
50
|
+
top-level namespace today:
|
|
51
|
+
|
|
52
|
+
| | Modern (singledispatch) | Legacy (flat, DataFrame-only) |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| Embedding | `plot_embedding` / `plot_reduced_dim` / `dim_plot` / `plot_umap` / `plot_pca` / `plot_tsne` | — |
|
|
55
|
+
| Expression violin | `plot_expression` | `expression_violin`, `expression_violin_sce`, `expression_violin_se` |
|
|
56
|
+
| Dot plot | `plot_dot` | `marker_dotplot`, `marker_dotplot_from_matrix`, `marker_dotplot_sce` |
|
|
57
|
+
| Heatmap | `plot_heatmap` | `heatmap_long`, `heatmap_from_matrix` |
|
|
58
|
+
| Volcano | `plot_volcano` | `volcano_plot` |
|
|
59
|
+
| Composition | `plot_abundance` | `cluster_composition_barplot` |
|
|
60
|
+
| QC scatter/hist | `plot_coldata` (covers scatter) | `qc_scatter`, `qc_histogram` |
|
|
61
|
+
| Ridge density | *(no modern replacement)* | `ridge_density` |
|
|
62
|
+
|
|
63
|
+
Every legacy function has a modern 1:1 replacement **except `ridge_density`** (gap —
|
|
64
|
+
no modern replacement exists, and it should be exempted from any deprecation until one
|
|
65
|
+
does) and the matrix-input convenience wrappers (`*_from_matrix`, which the modern
|
|
66
|
+
generics don't offer — see §4.7).
|
|
67
|
+
|
|
68
|
+
The legacy functions aren't dispatch-based, don't share the modern error-message or
|
|
69
|
+
non-mutation conventions, and use a different naming grammar entirely (`volcano_plot`,
|
|
70
|
+
`expression_violin`, `ridge_density` put the verb *after* the noun; `heatmap_long`,
|
|
71
|
+
`marker_dotplot` put a qualifier after the noun). Keeping ~15 of them in the same flat
|
|
72
|
+
`__all__` as the modern set is the single biggest source of "which function do I
|
|
73
|
+
use?" confusion right now — worse than any individual naming choice below.
|
|
74
|
+
|
|
75
|
+
## 4. Specific naming problems to resolve before declaring the API stable
|
|
76
|
+
|
|
77
|
+
### 4.1 `plot_embedding` has three names for one function — no distinct audiences
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
plot_reduced_dim = plot_embedding
|
|
81
|
+
dim_plot = plot_embedding
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
These are literal object aliases (`ggnomics/scatter.py:392-394`), not wrappers — same
|
|
85
|
+
function, same dispatch registry, three import names. `dim_plot` targets Seurat users
|
|
86
|
+
(`DimPlot`), `plot_reduced_dim` targets... the same audience as `plot_embedding`,
|
|
87
|
+
just with a different word for "embedding". It adds a name to remember without adding
|
|
88
|
+
a distinct mental model. Recommendation in §7.1.
|
|
89
|
+
|
|
90
|
+
### 4.2 `plot_pca` and `plot_umap` mean two different things depending on namespace
|
|
91
|
+
|
|
92
|
+
This is the sharpest landmine in the current API:
|
|
93
|
+
|
|
94
|
+
| Call | Behavior |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `gg.plot_pca(data, color=...)` | Displays an **already-computed** `X_pca` embedding. Container-dispatched (DataFrame/AnnData/SCE). Never runs PCA. |
|
|
97
|
+
| `gg.sc_pca.plot_pca(sce, run_if_missing=True, ...)` | **Computes** PCA via scikit-learn if missing, stores it in `reduced_dims`, then plots. SCE-only, not dispatched. |
|
|
98
|
+
| `gg.bulk_pca.plot_pca(se, pca_res=None, n_top_genes=None, ...)` | **Computes** PCA (optionally on top-variance genes) if `pca_res` not supplied, then plots. SE-only. |
|
|
99
|
+
|
|
100
|
+
Same name, three incompatible signatures and three different "does this run an
|
|
101
|
+
analysis?" answers, distinguished only by which submodule you happened to import
|
|
102
|
+
(`gg.plot_pca` vs `gg.sc_pca.plot_pca` vs `gg.bulk_pca.plot_pca`). The equivalent
|
|
103
|
+
collision exists for `plot_umap` vs `gg.sc_umap.plot_umap`. `bulk.pca` and
|
|
104
|
+
`singlecell.pca` are also ~80% duplicate code (`build_plot_df_from_sce` /
|
|
105
|
+
`build_plot_df_from_result` do the same "embedding + coldata → tidy DataFrame" job
|
|
106
|
+
that `_embedding_frame_from_dataframe` / `_embedding_frame` already do elsewhere).
|
|
107
|
+
|
|
108
|
+
This is also the one place where the "ggnomics is a visualization layer; BiocPy /
|
|
109
|
+
scranpy / PyDESeq2 / scverse do analysis" boundary stated in the README is violated —
|
|
110
|
+
`sc_pca.run_pca` / `bulk_pca.run_pca` are genuine analysis functions, not adapters.
|
|
111
|
+
Recommendation in §7.2.
|
|
112
|
+
|
|
113
|
+
### 4.3 `plot_coldata` re-implements what `plot_scatter` already does
|
|
114
|
+
|
|
115
|
+
For two numeric columns, `plot_coldata` builds its own `geom_point` + continuous
|
|
116
|
+
color-scale plot (`ggnomics/coldata.py:110-115`) rather than delegating to
|
|
117
|
+
`plot_scatter`, which does the identical thing with a more complete feature set
|
|
118
|
+
(facets, adaptive size/stroke, palettes, aspect ratio). `plot_bimodal_scatter`, by
|
|
119
|
+
contrast, does delegate to `plot_scatter` for its non-marginal case — showing the
|
|
120
|
+
delegation pattern is known and used elsewhere, just not applied consistently. Two
|
|
121
|
+
consequences: (a) any future improvement to `plot_scatter`'s numeric-numeric path
|
|
122
|
+
silently doesn't reach `plot_coldata`, and (b) it's not obvious to a new user *when*
|
|
123
|
+
to reach for `plot_scatter` vs `plot_coldata` — the honest answer today is "`plot_scatter`
|
|
124
|
+
takes any two columns; `plot_coldata` takes any two columns from obs/colData and adds
|
|
125
|
+
violin/box/bar for categorical x" i.e. `plot_coldata` is a strict superset scoped to
|
|
126
|
+
metadata. That scoping rule is real and worth keeping, but should be enforced by
|
|
127
|
+
delegation, not duplication.
|
|
128
|
+
|
|
129
|
+
### 4.4 Container-mediated modality selection has two competing conventions
|
|
130
|
+
|
|
131
|
+
`plot_bimodal_scatter`'s `AnnData` adapter accepts *both* `x_mod`/`y_mod` (older,
|
|
132
|
+
implicit: names an obsm/layer key) and `layer_x`/`layer_y` (newer, explicit layer
|
|
133
|
+
name), with the docstring itself noting `layer_x`/`layer_y` were added for backward
|
|
134
|
+
compatibility and take precedence. That's a sign the parameter design is still
|
|
135
|
+
settling — worth locking down before "stable" rather than after.
|
|
136
|
+
|
|
137
|
+
### 4.5 Inconsistent return type for the same visual family
|
|
138
|
+
|
|
139
|
+
`plot_heatmap` returns a bare `ggplot`. `plot_clonotype_overlap` and
|
|
140
|
+
`plot_coef_expression(plot_type="heatmap")` return `HeatmapResult` (a `ggplot` +
|
|
141
|
+
the underlying matrix) for what is visually the same geom (`geom_tile`). A user who
|
|
142
|
+
row-clusters with `plot_heatmap(cluster_rows=True)` gets back the *reordered* matrix
|
|
143
|
+
nowhere — they'd have to recompute clustering themselves to get row order. That's the
|
|
144
|
+
exact case `HeatmapResult` exists to solve for the other two callers.
|
|
145
|
+
|
|
146
|
+
### 4.6 Backend coverage is asymmetric in ways that look unintentional
|
|
147
|
+
|
|
148
|
+
Diffing the `.register()` calls across all four backends:
|
|
149
|
+
|
|
150
|
+
- **`SummarizedExperiment` never registers `plot_scatter`** (only
|
|
151
|
+
`plot_scatter_marginal`, which requires it internally). A bulk user cannot make a
|
|
152
|
+
plain x/y scatter of two `colData` columns through the dispatch API — looks like an
|
|
153
|
+
oversight, not a deliberate scope limit.
|
|
154
|
+
- **`SummarizedExperiment` *does* register `plot_adt_qc` and
|
|
155
|
+
`plot_clonotype_abundance`/`overlap`** — single-cell-protein and immune-repertoire
|
|
156
|
+
concepts, on a container whose defining trait is "no per-cell reduced dimensions."
|
|
157
|
+
Harmless if the columns exist, but it's not obvious this was a deliberate design
|
|
158
|
+
choice vs. mechanical copy-paste across backend files.
|
|
159
|
+
- **`MuData` registers only `plot_adt_qc` and `plot_bimodal_scatter`** — none of
|
|
160
|
+
`plot_embedding`, `plot_scatter`, `plot_expression`, `plot_coldata`, etc. have a
|
|
161
|
+
`MuData` adapter, so a `MuData` object is unusable for most of the library. This may
|
|
162
|
+
be intentional (MuData's whole point is cross-modality; maybe every other generic
|
|
163
|
+
is meant to be called on `mdata.mod["rna"]` directly), but it isn't documented as a
|
|
164
|
+
deliberate scope decision anywhere, so it currently reads as "unfinished."
|
|
165
|
+
- **Legacy `expression_violin` is registered for `SCE`/`SE` but not `AnnData`** — the
|
|
166
|
+
legacy API's own coverage is inconsistent, on top of being superseded.
|
|
167
|
+
|
|
168
|
+
### 4.7 No modern replacement for matrix-input convenience wrappers
|
|
169
|
+
|
|
170
|
+
`marker_dotplot_from_matrix` and `heatmap_from_matrix` (legacy) take a bare
|
|
171
|
+
`np.ndarray`/`DataFrame` matrix plus a group vector and do the aggregation themselves,
|
|
172
|
+
which is genuinely convenient when a user has a raw expression matrix and no tidy
|
|
173
|
+
`DataFrame` yet. The modern `plot_dot`/`plot_heatmap` generics only dispatch on
|
|
174
|
+
`DataFrame` and registered containers — there's no `ndarray` path. This isn't a naming
|
|
175
|
+
inconsistency like the others in this section, it's a real feature gap: deprecating
|
|
176
|
+
the legacy matrix wrappers per §7.3 without replacing them would remove capability,
|
|
177
|
+
not just rename it. Resolve by either registering `plot_dot`/`plot_heatmap` for
|
|
178
|
+
`np.ndarray` directly (consistent with the dispatch pattern used everywhere else) or
|
|
179
|
+
explicitly deciding matrix input is out of scope for the modern API and keeping the
|
|
180
|
+
two `*_from_matrix` legacy functions permanently exempt from deprecation.
|
|
181
|
+
|
|
182
|
+
### 4.8 `ggnomics/pca/` sits in an ambiguous public/private zone
|
|
183
|
+
|
|
184
|
+
`run_pca_sklearn`, `run_pca_svd`, `PcaResult` live in a package-visible path
|
|
185
|
+
(`ggnomics/pca/`, no leading underscore) but are deliberately **not** re-exported from
|
|
186
|
+
`ggnomics.__init__` — the plot-gallery article says so explicitly ("It is not
|
|
187
|
+
re-exported from the top-level namespace"). A no-underscore top-level subpackage is
|
|
188
|
+
normally read as "this is public, just deep"; right now it's public-by-path but
|
|
189
|
+
private-by-convention, which is exactly the kind of ambiguity that becomes a support
|
|
190
|
+
burden once users start `from ggnomics.pca import PcaResult`. Pick one (see §7.6).
|
|
191
|
+
|
|
192
|
+
## 5. The "levels" of plot you described, made explicit
|
|
193
|
+
|
|
194
|
+
Your framing (container extensions vs. results-table plots vs. everything else) is
|
|
195
|
+
accurate and is a good organizing axis for docs even if the file layout doesn't
|
|
196
|
+
change. Five kinds of public surface exist today:
|
|
197
|
+
|
|
198
|
+
1. **Container-dispatched plots** — the majority. Take a `DataFrame` *or* a registered
|
|
199
|
+
container; the container adapter reduces to the `DataFrame` case. Examples:
|
|
200
|
+
`plot_embedding` family, `plot_scatter`, `plot_coldata`/`plot_rowdata`,
|
|
201
|
+
`plot_expression`/`plot_dot`/`plot_heatmap`, `plot_abundance`,
|
|
202
|
+
`plot_highest_exprs`, `plot_pairs`, `plot_violin_stats`/`plot_box_stats`,
|
|
203
|
+
`plot_scatter_marginal`, `plot_embedding_panel`, `plot_bimodal_scatter`,
|
|
204
|
+
`plot_adt_qc`, `plot_clonotype_*`, `plot_pseudobulk_qc`.
|
|
205
|
+
2. **Results-table plots** — operate on a plain DE/coefficient/count table that has no
|
|
206
|
+
natural container form, so dispatch buys nothing. Examples: `plot_volcano`,
|
|
207
|
+
`plot_ma`, `plot_coef_lollipop`, `plot_pseudobulk_de`. `plot_coef_expression` is a
|
|
208
|
+
hybrid: it takes *both* a container/DataFrame (`data`, for expression) and a
|
|
209
|
+
results table (`coefs`, for feature selection) — worth calling out as its own
|
|
210
|
+
pattern rather than forcing it into one bucket.
|
|
211
|
+
3. **Compute + plot combos** — run an analysis, then plot the result. Currently only
|
|
212
|
+
`singlecell.pca`, `singlecell.umap`, `bulk.pca` (not exported at top level). This
|
|
213
|
+
is the one place analysis and visualization are fused, and it's the source of the
|
|
214
|
+
`plot_pca` collision in §4.2.
|
|
215
|
+
4. **Grammar extensions** — not "a plot", but new geoms/stats/scales for plotnine
|
|
216
|
+
itself, usable standalone: `ggnomics.signif` (`geom_signif`, `run_comparisons`,
|
|
217
|
+
`map_pvalue_to_stars`) and `ggnomics.upset` (a full ComplexUpset-style
|
|
218
|
+
compute→select→apply pipeline with its own ~35 exports). These are already
|
|
219
|
+
correctly scoped as their own subpackages/namespaces and don't need to change.
|
|
220
|
+
5. **Composition & palette utilities** — `hstack`/`vstack`/`grid`/
|
|
221
|
+
`annotate_composition`/`save_composition`; `get_palette`/`resolve_palette` +
|
|
222
|
+
palette constants. Cross-cutting, used by everything above.
|
|
223
|
+
|
|
224
|
+
Formalizing these five categories (in docs navigation, and in a short "how to name a
|
|
225
|
+
new function" note in `CONTRIBUTING.md`) will do most of the organizational work you're
|
|
226
|
+
after, independent of any renaming below.
|
|
227
|
+
|
|
228
|
+
## 6. Recommended naming convention going forward
|
|
229
|
+
|
|
230
|
+
A new public plot function should satisfy:
|
|
231
|
+
|
|
232
|
+
- **Prefix**: `plot_` for anything returning `ggplot` or `Compose`. No exceptions —
|
|
233
|
+
this is already true for 100% of the modern set and should stay a hard rule.
|
|
234
|
+
- **Subject, not container**: the name describes *what* is plotted
|
|
235
|
+
(`embedding`, `coldata`, `expression`, `volcano`), never the input type. Already
|
|
236
|
+
followed everywhere in the modern set — keep enforcing it.
|
|
237
|
+
- **Qualifiers as suffixes, not alternate verbs**: `_stats` for automatic
|
|
238
|
+
significance annotation (`plot_violin_stats`, `plot_box_stats`), `_panel`/`_marginal`
|
|
239
|
+
for multi-panel composition (`plot_embedding_panel`, `plot_scatter_marginal`). This
|
|
240
|
+
convention already exists and reads well — codify it explicitly so new functions
|
|
241
|
+
follow it instead of inventing a new pattern (e.g. a hypothetical future
|
|
242
|
+
"expression + stats" function should be `plot_expression_stats`, not
|
|
243
|
+
`plot_stat_expression` or `plot_expression_with_stats`).
|
|
244
|
+
- **At most one familiarity alias per function**, and it must be declared as an alias,
|
|
245
|
+
not shipped as an equal-weight second name. See §7.1.
|
|
246
|
+
- **Compute-then-plot functions get their own verb**, never `plot_*`. See §7.2.
|
|
247
|
+
|
|
248
|
+
## 7. Decisions to make
|
|
249
|
+
|
|
250
|
+
### 7.1 Collapse the embedding aliases
|
|
251
|
+
|
|
252
|
+
Recommendation: **`plot_embedding` is canonical.** It's the most general (any
|
|
253
|
+
`obsm`/`reducedDims` key, not just PCA/UMAP/t-SNE) and already mirrors
|
|
254
|
+
`scanpy.pl.embedding`, which is the convention most of your target audience already
|
|
255
|
+
knows.
|
|
256
|
+
|
|
257
|
+
- Drop `plot_reduced_dim` — it's a pure synonym of `plot_embedding` with no distinct
|
|
258
|
+
audience; keeping it only doubles the surface a user has to learn is "the same
|
|
259
|
+
thing."
|
|
260
|
+
- Keep `dim_plot` **only** as a documented Seurat-familiarity alias (one line in the
|
|
261
|
+
docstring: "alias of `plot_embedding`, for users coming from Seurat's `DimPlot`"),
|
|
262
|
+
not as an equal `__all__` entry with its own doc page.
|
|
263
|
+
- Keep `plot_umap`/`plot_pca`/`plot_tsne` — these are legitimate convenience wrappers
|
|
264
|
+
(fixed `dimred=`), not synonyms, and match `scanpy.pl.umap`/`.pca`/`.tsne` closely
|
|
265
|
+
enough to lower the adoption cost. (`plot_pca` needs the fix in §7.2 first.)
|
|
266
|
+
|
|
267
|
+
### 7.2 Split "compute" from "plot" for PCA/UMAP
|
|
268
|
+
|
|
269
|
+
The `plot_pca`/`plot_umap` name collision (§4.2) should be resolved by removing the
|
|
270
|
+
second definition, not by renaming around it. Two ways to get there — pick one:
|
|
271
|
+
|
|
272
|
+
**Option A — compute-only helpers, single plot entry point (recommended).**
|
|
273
|
+
Rename `sc_pca.plot_pca` → drop it entirely; `sc_pca.run_pca` keeps computing and
|
|
274
|
+
storing the embedding, and the user calls the one canonical `gg.plot_pca` /
|
|
275
|
+
`gg.plot_embedding` on the result afterward, exactly as they already do for any
|
|
276
|
+
precomputed embedding. Same for `sc_umap`/`bulk_pca`. This is a small deletion (the
|
|
277
|
+
`plot_pca`/`plot_umap` wrappers in `singlecell/pca.py`, `singlecell/umap.py`,
|
|
278
|
+
`bulk/pca.py` are ~15 lines each of pure pass-through to `plot_embedding` already) and
|
|
279
|
+
it makes the analysis/visualization boundary from the README literally true in code,
|
|
280
|
+
not just in prose. It also removes the `build_plot_df_from_sce`/
|
|
281
|
+
`build_plot_df_from_result` duplication for free, since there's no longer a
|
|
282
|
+
compute-module-local plot path to feed.
|
|
283
|
+
|
|
284
|
+
**Option B — keep the combo, rename it out of the `plot_` namespace.** e.g.
|
|
285
|
+
`sc_pca.compute_embedding(sce, ..., plot=True)` or a distinctly-named
|
|
286
|
+
`sc.pca(...)` / `bulk.pca(...)` callable that isn't spelled `plot_pca`. Lower-value
|
|
287
|
+
than A (keeps two ways to do the same thing) but preserves the one-call convenience
|
|
288
|
+
some users may like for exploratory work.
|
|
289
|
+
|
|
290
|
+
Either way, this is the highest-priority fix in this document: it's the one place two
|
|
291
|
+
functions with the *identical name* do observably different things depending on
|
|
292
|
+
import path, which is the kind of surprise that erodes trust in a "stable" API fast.
|
|
293
|
+
|
|
294
|
+
### 7.3 Retire the legacy namespace as a namespace, not just individually
|
|
295
|
+
|
|
296
|
+
Rather than leaving ~15 legacy functions permanently mixed into the root `__all__`
|
|
297
|
+
next to their modern replacements, move them behind `ggnomics.legacy`:
|
|
298
|
+
|
|
299
|
+
1. Now: add a `DeprecationWarning` inside each legacy function pointing at its modern
|
|
300
|
+
replacement (table in §3), keep the root-level import working.
|
|
301
|
+
2. Next minor version: move the definitions under `ggnomics/legacy/` (or keep the
|
|
302
|
+
files where they are and just re-export from `ggnomics.legacy`), stop importing
|
|
303
|
+
them into `ggnomics.__all__` directly — `import ggnomics.legacy as gglegacy` still
|
|
304
|
+
works, `ggnomics.volcano_plot` starts raising `AttributeError` with a message
|
|
305
|
+
pointing at `ggnomics.legacy.volcano_plot`.
|
|
306
|
+
3. Next major version: delete.
|
|
307
|
+
|
|
308
|
+
`ridge_density` (no modern replacement, §3) and the `*_from_matrix` convenience
|
|
309
|
+
wrappers (§4.7) are the two exceptions — decide whether those get a modern
|
|
310
|
+
replacement before deprecating, or get promoted (rather than deprecated) since they
|
|
311
|
+
fill a real gap.
|
|
312
|
+
|
|
313
|
+
### 7.4 Fill or document the backend-coverage gaps (§4.6)
|
|
314
|
+
|
|
315
|
+
- Register `plot_scatter` for `SummarizedExperiment` (looks like a straightforward
|
|
316
|
+
bug fix, not a design question).
|
|
317
|
+
- For `MuData`'s narrow coverage: either (a) write adapters for the rest of the
|
|
318
|
+
container-dispatched set (treating a `MuData` mostly like "AnnData with a modality
|
|
319
|
+
selector"), or (b) keep it scoped to cross-modality functions and add one sentence
|
|
320
|
+
to the docs/README stating that scope explicitly, so it reads as a decision rather
|
|
321
|
+
than an omission. Given multimodal is already flagged as a smaller, newer surface
|
|
322
|
+
area, (b) is the lower-effort and probably-correct near-term choice — just make it
|
|
323
|
+
explicit.
|
|
324
|
+
- Decide whether `plot_adt_qc`/`plot_clonotype_*` on `SummarizedExperiment` is
|
|
325
|
+
intentional generality (works if the columns exist, no harm) or should be narrowed;
|
|
326
|
+
either is defensible, but it should be a recorded decision.
|
|
327
|
+
|
|
328
|
+
### 7.5 Decide the `HeatmapResult` policy
|
|
329
|
+
|
|
330
|
+
Recommendation: return `HeatmapResult` from `plot_heatmap` whenever
|
|
331
|
+
`cluster_rows`/`cluster_cols` reorders the matrix (the reordered matrix is exactly the
|
|
332
|
+
derived artifact the caller can't otherwise recover), and a bare `ggplot` when no
|
|
333
|
+
clustering happened — matching the existing rule that `HeatmapResult` marks "this
|
|
334
|
+
call produced a matrix you couldn't already reconstruct."
|
|
335
|
+
|
|
336
|
+
### 7.6 Decide `ggnomics/pca/`'s visibility (§4.8)
|
|
337
|
+
|
|
338
|
+
Either rename to `ggnomics/_pca/` to make "internal plumbing" true by path (cheapest,
|
|
339
|
+
recommended if the sklearn/SVD PCA core isn't meant to be a public API in its own
|
|
340
|
+
right), or keep the path and add it to `ggnomics.__all__` with the same documentation
|
|
341
|
+
weight as everything else (only worth it if there's a real audience for calling
|
|
342
|
+
`run_pca_sklearn` directly rather than through `sc_pca`/`bulk_pca`).
|
|
343
|
+
|
|
344
|
+
## 8. Suggested sequencing
|
|
345
|
+
|
|
346
|
+
1. Fix §7.2 (the `plot_pca`/`plot_umap` collision) — highest confusion-per-line-of-fix
|
|
347
|
+
ratio, and a pure subtraction (Option A deletes code, doesn't add any).
|
|
348
|
+
2. Fix §7.1 (drop `plot_reduced_dim`, demote `dim_plot` to a documented alias) —
|
|
349
|
+
another pure subtraction from `__all__`.
|
|
350
|
+
3. Land §4.3 (`plot_coldata` delegates to `plot_scatter` for the numeric/numeric case)
|
|
351
|
+
and §4.5 (`HeatmapResult` policy) — internal correctness fixes, no public API
|
|
352
|
+
change, but they remove behavior that would otherwise need to be preserved forever
|
|
353
|
+
once "stable" is declared.
|
|
354
|
+
4. Start the §7.3 legacy-deprecation clock (add warnings now, move the namespace in
|
|
355
|
+
the next minor release) — this is the change most visible to existing users, so it
|
|
356
|
+
should go out with the most advance notice.
|
|
357
|
+
5. §7.4/§7.5/§7.6 can land opportunistically — they're gaps and small inconsistencies,
|
|
358
|
+
not landmines, so they don't block declaring the rest of the API stable.
|
|
359
|
+
|
|
360
|
+
Once 1–4 are done, the "modern" `plot_*` set (§5, category 1) plus `plot_volcano`/
|
|
361
|
+
`plot_ma`/`plot_coef_*`/`plot_pseudobulk_de` (category 2), `ggnomics.signif`,
|
|
362
|
+
`ggnomics.upset`, and the composition/palette utilities are in good shape to freeze as
|
|
363
|
+
`ggnomics` 1.0's public surface.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Authors
|
|
2
|
+
|
|
3
|
+
ggnomics is developed and maintained by:
|
|
4
|
+
|
|
5
|
+
* **MaximilianNuber** — [maximilian.d.nuber@gmail.com](mailto:maximilian.d.nuber@gmail.com)
|
|
6
|
+
|
|
7
|
+
## Contributors
|
|
8
|
+
|
|
9
|
+
Contributions from the community are listed here as they arrive. See
|
|
10
|
+
[CONTRIBUTING.md](https://github.com/MaximilianNuber/ggnomics/blob/main/CONTRIBUTING.md) to get started.
|
|
11
|
+
|
|
12
|
+
Automated commits by `github-actions[bot]` (README plot regeneration) are not
|
|
13
|
+
listed as authorship.
|
|
14
|
+
|
|
15
|
+
## Acknowledgements
|
|
16
|
+
|
|
17
|
+
ggnomics builds on, and is designed to work alongside, the following projects:
|
|
18
|
+
|
|
19
|
+
* [plotnine](https://plotnine.org) — the grammar-of-graphics implementation
|
|
20
|
+
every ggnomics function returns objects from.
|
|
21
|
+
* [BiocPy](https://github.com/BiocPy) — `SingleCellExperiment`,
|
|
22
|
+
`SummarizedExperiment`, `BiocFrame`, and the data-access packages used in the
|
|
23
|
+
workflow guides.
|
|
24
|
+
* [scverse](https://scverse.org) — AnnData and MuData.
|
|
25
|
+
* [ComplexUpset](https://github.com/krassowski/complex-upset) — the design that
|
|
26
|
+
`ggnomics.upset` follows.
|
|
27
|
+
* [Marsilea](https://marsilea.readthedocs.io) — composable heatmaps.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to ggnomics are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Development tooling: `tox.ini` (`py`, `core`, `lint`, `format`, `build`,
|
|
13
|
+
`docs`, `linkcheck`), `.pre-commit-config.yaml`, and Ruff lint/format
|
|
14
|
+
configuration in `pyproject.toml`.
|
|
15
|
+
- `tools/check_internal_links.py`, an offline internal-link checker for the
|
|
16
|
+
rendered Quarto site.
|
|
17
|
+
- `tests/test_public_api_contract.py`: return-type contracts, non-mutation
|
|
18
|
+
guarantees for DataFrame / AnnData / `SingleCellExperiment` /
|
|
19
|
+
`SummarizedExperiment` inputs, and error-message checks for unsupported
|
|
20
|
+
containers.
|
|
21
|
+
- Project documents: `CONTRIBUTING.md`, `CHANGELOG.md`, `AUTHORS.md`,
|
|
22
|
+
`CODE_OF_CONDUCT.md`, plus pull-request and issue templates.
|
|
23
|
+
- GitHub Actions workflows for documentation validation and for PyPI trusted
|
|
24
|
+
publishing (the trusted publisher itself is not yet configured).
|
|
25
|
+
- Automatic versioning with `setuptools_scm`: the version is derived from the
|
|
26
|
+
git tag, written to the generated `ggnomics/_version.py` at build time, and
|
|
27
|
+
exposed as `ggnomics.__version__`. `MANIFEST.in` keeps the sdist to the
|
|
28
|
+
package plus its test suite, since setuptools_scm's file finder would
|
|
29
|
+
otherwise ship the whole documentation tree.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- The "UpSet plots" vignette now appears in the site navigation bar and is
|
|
34
|
+
linked from the documentation home page.
|
|
35
|
+
- `pyproject.toml` metadata completed: real author and maintainer information,
|
|
36
|
+
classifiers, keywords, and the full set of project URLs. The `docs` extra now
|
|
37
|
+
installs quartodoc instead of MkDocs.
|
|
38
|
+
- Coverage configuration added; the full suite covers about 83% of `ggnomics/`
|
|
39
|
+
and CI enforces a floor of 80%.
|
|
40
|
+
- The test workflow matrix now covers Python 3.10, 3.12, and 3.13.
|
|
41
|
+
- `pyproject.toml` no longer carries a static `version`; it is `dynamic`.
|
|
42
|
+
|
|
43
|
+
### Removed
|
|
44
|
+
|
|
45
|
+
- The legacy MkDocs site (`mkdocs.yml`, `docs/index.md`, `docs/vignettes.md`,
|
|
46
|
+
`docs/api/*.md`). Quarto with quartodoc is the single documentation renderer.
|
|
47
|
+
`docs/img/` and `docs/generate_readme_plots.py` are unaffected.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Two bare `except:` clauses in `ggnomics/singlecell/` narrowed to
|
|
52
|
+
`except Exception:` so `KeyboardInterrupt` and `SystemExit` propagate.
|
|
53
|
+
- `run_umap` now chains the original `ImportError` when `umap-learn` is missing.
|
|
54
|
+
- The "many groups" warning in `ggnomics.signif` now reports the caller's
|
|
55
|
+
location via `stacklevel=2`.
|
|
56
|
+
- Removed dead assignments in `ggnomics/dotplot.py` and in several tests; one
|
|
57
|
+
test asserted on a variable that was never bound.
|
|
58
|
+
|
|
59
|
+
## [0.1.0]
|
|
60
|
+
|
|
61
|
+
Initial release.
|
|
62
|
+
|
|
63
|
+
- `plot_*` plotting functions built on `functools.singledispatch`, returning
|
|
64
|
+
ordinary plotnine objects.
|
|
65
|
+
- Backends for AnnData, BiocPy `SingleCellExperiment` and
|
|
66
|
+
`SummarizedExperiment`, and MuData, registered lazily and only when the
|
|
67
|
+
corresponding package is installed.
|
|
68
|
+
- Native plotnine UpSet plots and Venn diagrams (`ggnomics.upset`).
|
|
69
|
+
- Significance brackets and statistical annotations (`ggnomics.signif`).
|
|
70
|
+
- Marsilea-backed composable heatmaps.
|
|
71
|
+
- Quarto workflow guides and a quartodoc-generated API reference.
|
|
72
|
+
|
|
73
|
+
[Unreleased]: https://github.com/MaximilianNuber/ggnomics/compare/main...HEAD
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
# Contributor Covenant Code of Conduct
|
|
3
|
+
|
|
4
|
+
## Our Pledge
|
|
5
|
+
|
|
6
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
7
|
+
|
|
8
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
9
|
+
|
|
10
|
+
## Our Standards
|
|
11
|
+
|
|
12
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
|
13
|
+
|
|
14
|
+
* Demonstrating empathy and kindness toward other people
|
|
15
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
16
|
+
* Giving and gracefully accepting constructive feedback
|
|
17
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
18
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
19
|
+
|
|
20
|
+
Examples of unacceptable behavior include:
|
|
21
|
+
|
|
22
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
23
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
24
|
+
* Public or private harassment
|
|
25
|
+
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
26
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
27
|
+
|
|
28
|
+
## Enforcement Responsibilities
|
|
29
|
+
|
|
30
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
31
|
+
|
|
32
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
|
33
|
+
|
|
34
|
+
## Scope
|
|
35
|
+
|
|
36
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
|
37
|
+
|
|
38
|
+
## Enforcement
|
|
39
|
+
|
|
40
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at maximilian.d.nuber@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
|
|
41
|
+
|
|
42
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
|
43
|
+
|
|
44
|
+
## Enforcement Guidelines
|
|
45
|
+
|
|
46
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
|
47
|
+
|
|
48
|
+
### 1. Correction
|
|
49
|
+
|
|
50
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
|
51
|
+
|
|
52
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
|
53
|
+
|
|
54
|
+
### 2. Warning
|
|
55
|
+
|
|
56
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
|
57
|
+
|
|
58
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
|
59
|
+
|
|
60
|
+
### 3. Temporary Ban
|
|
61
|
+
|
|
62
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
|
63
|
+
|
|
64
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
|
65
|
+
|
|
66
|
+
### 4. Permanent Ban
|
|
67
|
+
|
|
68
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
|
69
|
+
|
|
70
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
|
71
|
+
|
|
72
|
+
## Attribution
|
|
73
|
+
|
|
74
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
75
|
+
|
|
76
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
77
|
+
|
|
78
|
+
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
|
|
79
|
+
|
|
80
|
+
[homepage]: https://www.contributor-covenant.org
|
|
81
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
82
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
83
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
84
|
+
[translations]: https://www.contributor-covenant.org/translations
|