scistackplot 0.1.57__tar.gz → 0.1.59__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.
- {scistackplot-0.1.57 → scistackplot-0.1.59}/PKG-INFO +3 -3
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/cell.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/codegen.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/custom.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/reduce.py +5 -5
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/render/mpl.py +4 -4
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/render/plotly_.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/textsize.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/variants.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/ylimits.py +1 -1
- {scistackplot-0.1.57 → scistackplot-0.1.59}/.gitignore +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/README.md +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/pyproject.toml +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/__init__.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/aliases.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/autosize.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/bins.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/capability.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/colors.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/compare.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/dedup.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/design.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/diffbars.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/export.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/figsize.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/figure_file.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/fits.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/framesize.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/groups.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/numeric.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/panels.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/paper.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/presets.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/reducer.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/render/__init__.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/render/base.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/resolved.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/restore.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/roles.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/series_stats.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/shape.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/sources/__init__.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/sources/base.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/sources/csv.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/sources/frame.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/spaghetti.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/spec.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/spread.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/table.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/temporal.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/ticklabels.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/weights.py +0 -0
- {scistackplot-0.1.57 → scistackplot-0.1.59}/src/scistackplot/xaxis.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: scistackplot
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.59
|
|
4
4
|
Summary: Spec-driven plotting for long-format scientific data — standalone, GUI-friendly
|
|
5
5
|
Author: SciStack Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,8 +20,8 @@ Requires-Python: >=3.10
|
|
|
20
20
|
Requires-Dist: csv-stats>=0.5.0
|
|
21
21
|
Requires-Dist: numpy>=1.21
|
|
22
22
|
Requires-Dist: pandas>=1.5
|
|
23
|
-
Requires-Dist: scicanonicalhash==0.1.
|
|
24
|
-
Requires-Dist: scistacklog==0.1.
|
|
23
|
+
Requires-Dist: scicanonicalhash==0.1.59
|
|
24
|
+
Requires-Dist: scistacklog==0.1.59
|
|
25
25
|
Provides-Extra: dev
|
|
26
26
|
Requires-Dist: matplotlib>=3.6; extra == 'dev'
|
|
27
27
|
Requires-Dist: plotly>=5.0; extra == 'dev'
|
|
@@ -126,7 +126,7 @@ def apply_cell_collapse(spec: PlotSpec, table: LongTable) -> LongTable:
|
|
|
126
126
|
# counts the factor summary reports, so "this trial recorded nothing"
|
|
127
127
|
# would read as "this trial does not exist".
|
|
128
128
|
#
|
|
129
|
-
# DEBUG: SOME empty cells are ordinary data (78 WARNs in
|
|
129
|
+
# DEBUG: SOME empty cells are ordinary data (78 WARNs in scistack.log
|
|
130
130
|
# 2026-10-19). The case worth a WARN — nothing at all to draw — is
|
|
131
131
|
# `all_nan_warning`'s, over the post-filter rows.
|
|
132
132
|
Log.debug(
|
|
@@ -874,7 +874,7 @@ def _preamble(spec, table, roles, shape) -> list[str]:
|
|
|
874
874
|
# Vectorized, not `.agg(' | '.join, axis=1)`. That form reads better
|
|
875
875
|
# and costs a Python call PER ROW, which for a 1-D measure is per
|
|
876
876
|
# sample: a 24-row frame of EMG traces is 8.9 million rows once
|
|
877
|
-
# exploded, and the join alone ran for minutes (
|
|
877
|
+
# exploded, and the join alone ran for minutes (scistack.log 2026-09-11).
|
|
878
878
|
lines.extend(
|
|
879
879
|
[
|
|
880
880
|
(
|
|
@@ -83,7 +83,7 @@ class CustomFunctionError(RuntimeError):
|
|
|
83
83
|
|
|
84
84
|
The message names the function and the call (figure and panel), so the
|
|
85
85
|
panel can say which call failed; the original exception is ``__cause__``
|
|
86
|
-
and its traceback is in
|
|
86
|
+
and its traceback is in scistack.log.
|
|
87
87
|
"""
|
|
88
88
|
|
|
89
89
|
|
|
@@ -466,7 +466,7 @@ class _Plan:
|
|
|
466
466
|
#: limits per kind. Until 2026-09-14 a LINE -> BAND switch was a cache HIT
|
|
467
467
|
#: that drew the band inside the line's limits. Memoised per mode rather
|
|
468
468
|
#: than added to the key, so a kind switch still costs only the limits
|
|
469
|
-
#: (25 ms in
|
|
469
|
+
#: (25 ms in scistack.log) and never the variants, filters and fan-out.
|
|
470
470
|
#:
|
|
471
471
|
#: The one field of a cached plan that is written after construction —
|
|
472
472
|
#: under `_plan_cache_lock`, and only ever ADDED to; `replace()` copies
|
|
@@ -1296,7 +1296,7 @@ def _build_figure(
|
|
|
1296
1296
|
axis_frame: pd.DataFrame | None = None,
|
|
1297
1297
|
) -> ResolvedPlot:
|
|
1298
1298
|
# ``narrate`` makes this function announce each phase as it starts. A
|
|
1299
|
-
# full-resolution figure is minutes of work (
|
|
1299
|
+
# full-resolution figure is minutes of work (scistack.log 2026-09-11: 1543s for
|
|
1300
1300
|
# two of them), and until the phases said so while they ran, the only
|
|
1301
1301
|
# evidence available was one summary line that a timed-out save never
|
|
1302
1302
|
# reached. The interactive path leaves it off: at 20k rows the narration
|
|
@@ -1816,7 +1816,7 @@ def _build_figure(
|
|
|
1816
1816
|
bins=figure_bins,
|
|
1817
1817
|
)
|
|
1818
1818
|
# Which difference bars land on which panel, once per figure, so a bar
|
|
1819
|
-
# that draws nowhere is explained in
|
|
1819
|
+
# that draws nowhere is explained in scistack.log (diffbars D3).
|
|
1820
1820
|
log_difference_bars(resolved)
|
|
1821
1821
|
return resolved
|
|
1822
1822
|
|
|
@@ -2284,7 +2284,7 @@ def _composed_key(
|
|
|
2284
2284
|
| ".join, axis=1)`` is a Python call **per row**, and the interactive path
|
|
2285
2285
|
never paid it because ``_downsample`` runs first (20 015 rows instead of
|
|
2286
2286
|
8 906 400). At full resolution — the save path, and only the save path — one
|
|
2287
|
-
figure took ~770s (
|
|
2287
|
+
figure took ~770s (scistack.log 2026-09-11, 1543s for two).
|
|
2288
2288
|
|
|
2289
2289
|
So: factorize each column (one C-level hash pass), fold the codes together
|
|
2290
2290
|
into a dense combination id, build the text ONCE per distinct combination,
|
|
@@ -2637,7 +2637,7 @@ def _unlabelled_x_order(panels: list[Panel]) -> list[Any] | None:
|
|
|
2637
2637
|
order at all and read as NUMERIC: plotly still drew the bars (it builds
|
|
2638
2638
|
its own category axis from the ``""`` strings) but every "Show sample"
|
|
2639
2639
|
overlay was silently dropped, and the matplotlib export placed the bars
|
|
2640
|
-
at NaN (
|
|
2640
|
+
at NaN (scistack.log 2026-09-21: colour by ColName with ColName the only
|
|
2641
2641
|
grouping layer).
|
|
2642
2642
|
"""
|
|
2643
2643
|
for panel in panels:
|
|
@@ -85,7 +85,7 @@ LAYER = "scistackplot"
|
|
|
85
85
|
#: on its own thread, and a render sets text sizes through ``rc_context`` —
|
|
86
86
|
#: GLOBAL rcParams, saved on entry and restored on exit — so two renders
|
|
87
87
|
#: overlapping (a pane resize while the previous resolve still lays out;
|
|
88
|
-
#:
|
|
88
|
+
#: scistack.log 2026-10-15 12:23:50, three at once) read each other's sizes and
|
|
89
89
|
#: the last to exit can leave the wrong ones behind. Re-entrant: a layout
|
|
90
90
|
#: decision settles the auto text size, whose trials render.
|
|
91
91
|
_MPL_LOCK = threading.RLock()
|
|
@@ -139,7 +139,7 @@ def _render(resolved: ResolvedPlot):
|
|
|
139
139
|
with Log.timer("render_mpl", layer=LAYER, extra=str(resolved.kind)) as timer:
|
|
140
140
|
# Consecutive laps rather than nested phases: the body is one long
|
|
141
141
|
# sequence, and which pass of it is slow is the question a slow
|
|
142
|
-
# figure asks (
|
|
142
|
+
# figure asks (scistack.log 2026-10-15: 6.6 s with no breakdown).
|
|
143
143
|
mark = time.perf_counter()
|
|
144
144
|
|
|
145
145
|
def lap(name: str) -> None:
|
|
@@ -708,7 +708,7 @@ def _draw_sample(ax, panel, resolved: ResolvedPlot) -> tuple[int, int]:
|
|
|
708
708
|
# lines: one artist per run made a figure whose innermost tick is a
|
|
709
709
|
# between-subject factor (group) draw ~1400 scatters, and every layout
|
|
710
710
|
# pass walks every artist — 6.6 s per render, 46 s with the auto text
|
|
711
|
-
# size's trials (
|
|
711
|
+
# size's trials (scistack.log 2026-10-15 12:21). Same points, same paint.
|
|
712
712
|
lone: dict[str, tuple[list[float], list[float]]] = {}
|
|
713
713
|
artists = 0
|
|
714
714
|
# (position, value) -> screen (x, y): a horizontal kind draws its
|
|
@@ -2305,7 +2305,7 @@ def layout_decisions(
|
|
|
2305
2305
|
out at every reference it tries, and a layout depends on the auto result
|
|
2306
2306
|
only through its ``reference`` (``textsize.sizes_for``). So the trial at
|
|
2307
2307
|
the chosen reference IS the final layout, and its decisions are kept
|
|
2308
|
-
rather than drawn again (
|
|
2308
|
+
rather than drawn again (scistack.log 2026-10-16: the redraw was ~0.4 s of
|
|
2309
2309
|
every ~0.85 s next/previous click). A custom kind's trial skips the
|
|
2310
2310
|
user's function (``custom.measuring``), so it is always drawn again.
|
|
2311
2311
|
"""
|
|
@@ -918,7 +918,7 @@ def _sample_traces(
|
|
|
918
918
|
# Lone points (not joined: a points-only overlay, or a one-point run)
|
|
919
919
|
# of one legend group and colour share ONE markers trace — one trace per
|
|
920
920
|
# run was ~1400 traces when the innermost tick is a between-subject
|
|
921
|
-
# factor (
|
|
921
|
+
# factor (scistack.log 2026-10-15), each one an SVG group in the browser.
|
|
922
922
|
# Same points, same legend group (hiding a level still hides them).
|
|
923
923
|
lone: dict[tuple[str, str], dict] = {}
|
|
924
924
|
runs = sample_runs(sample, resolved)
|
|
@@ -295,7 +295,7 @@ def _unsettled_reference(text: TextSizes) -> float:
|
|
|
295
295
|
|
|
296
296
|
Renderers settle first (``autosize.settle``), so this is reached only by a
|
|
297
297
|
caller sizing text outside a render — a size estimate, a test, a describe.
|
|
298
|
-
Logged at DEBUG so a renderer that forgot to settle shows up in
|
|
298
|
+
Logged at DEBUG so a renderer that forgot to settle shows up in scistack.log
|
|
299
299
|
as this line next to its own render line.
|
|
300
300
|
"""
|
|
301
301
|
span = reference_range(text)
|
|
@@ -520,7 +520,7 @@ def auto_label(
|
|
|
520
520
|
``RawEMG · low_hz=20``. A row's subject is the variable it draws; the
|
|
521
521
|
selection only narrows it. Naming rows by their selection alone was how two
|
|
522
522
|
rows reading "current" and "latest" ended up saying nothing about which was
|
|
523
|
-
EMG and which was force (observed 2026-09-11,
|
|
523
|
+
EMG and which was force (observed 2026-09-11, scistack.log 12:26:18).
|
|
524
524
|
|
|
525
525
|
``variable`` is the row's own, or the primary measure when it names none.
|
|
526
526
|
Callers pass it; this function never guesses.
|
|
@@ -187,7 +187,7 @@ def eligible_scope(
|
|
|
187
187
|
dropped = [name for name in wanted if name not in allowed]
|
|
188
188
|
if dropped:
|
|
189
189
|
# DEBUG, not WARN: the panel shows the eligible scope, and this fired
|
|
190
|
-
# on every resolve of an unchanged plot (31x in
|
|
190
|
+
# on every resolve of an unchanged plot (31x in scistack.log 2026-10-19).
|
|
191
191
|
Log.debug(
|
|
192
192
|
"y-limit scope ignores %s: only factors that separate PANELS "
|
|
193
193
|
"(iterate, facet) can separate y limits — %s. Limits will be shared "
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|