scistackplot 0.1.38__tar.gz → 0.1.39__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.38 → scistackplot-0.1.39}/PKG-INFO +2 -2
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/render/mpl.py +92 -29
- {scistackplot-0.1.38 → scistackplot-0.1.39}/.gitignore +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/README.md +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/pyproject.toml +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/__init__.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/aliases.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/autosize.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/capability.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/cell.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/codegen.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/colors.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/compare.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/custom.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/dedup.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/diffbars.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/export.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/figsize.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/figure_file.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/framesize.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/groups.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/numeric.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/panels.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/paper.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/presets.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/reduce.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/reducer.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/render/__init__.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/render/base.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/render/plotly_.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/resolved.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/restore.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/roles.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/series_stats.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/shape.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/sources/__init__.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/sources/base.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/sources/csv.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/sources/frame.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/spaghetti.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/spec.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/table.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/textsize.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/ticklabels.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/variants.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/weights.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/xaxis.py +0 -0
- {scistackplot-0.1.38 → scistackplot-0.1.39}/src/scistackplot/ylimits.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.39
|
|
4
4
|
Summary: Spec-driven plotting for long-format scientific data — standalone, GUI-friendly
|
|
5
5
|
Author: SciStack Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
|
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
20
|
Requires-Dist: numpy>=1.21
|
|
21
21
|
Requires-Dist: pandas>=1.5
|
|
22
|
-
Requires-Dist: scistacklog==0.1.
|
|
22
|
+
Requires-Dist: scistacklog==0.1.39
|
|
23
23
|
Provides-Extra: dev
|
|
24
24
|
Requires-Dist: matplotlib>=3.6; extra == 'dev'
|
|
25
25
|
Requires-Dist: plotly>=5.0; extra == 'dev'
|
|
@@ -1900,6 +1900,14 @@ def layout_decisions(
|
|
|
1900
1900
|
"width_in", "height_in"}``. The plotly preview
|
|
1901
1901
|
applies these rather than estimating text of its own, so what the preview
|
|
1902
1902
|
shows and what the file gets cannot come from two different rules.
|
|
1903
|
+
|
|
1904
|
+
One layout, not two: the auto text size search already lays the figure
|
|
1905
|
+
out at every reference it tries, and a layout depends on the auto result
|
|
1906
|
+
only through its ``reference`` (``textsize.sizes_for``). So the trial at
|
|
1907
|
+
the chosen reference IS the final layout, and its decisions are kept
|
|
1908
|
+
rather than drawn again (scidb.log 2026-10-16: the redraw was ~0.4 s of
|
|
1909
|
+
every ~0.85 s next/previous click). A custom kind's trial skips the
|
|
1910
|
+
user's function (``custom.measuring``), so it is always drawn again.
|
|
1903
1911
|
"""
|
|
1904
1912
|
import matplotlib.pyplot as plt
|
|
1905
1913
|
|
|
@@ -1911,37 +1919,87 @@ def layout_decisions(
|
|
|
1911
1919
|
with _one_figure_at_a_time("layout_decisions"), Log.timer(
|
|
1912
1920
|
"layout_decisions", layer=LAYER, extra=f"{width:.2f}x{height:.2f}in"
|
|
1913
1921
|
):
|
|
1922
|
+
# {reference: decisions} of each auto-size trial laid out here.
|
|
1923
|
+
trials: dict[float, dict] = {}
|
|
1924
|
+
|
|
1925
|
+
def measure(candidate: ResolvedPlot):
|
|
1926
|
+
decisions: dict = {}
|
|
1927
|
+
report = _layout_report(candidate, decisions_out=decisions)
|
|
1928
|
+
trials[candidate.auto_text.reference] = decisions
|
|
1929
|
+
return report
|
|
1930
|
+
|
|
1931
|
+
reusable = resolved.kind is not PlotKind.CUSTOM
|
|
1914
1932
|
# Auto text is chosen at the size being decided (the pane's, in Fit
|
|
1915
1933
|
# pane), keyed on the caller's object so the preview's later
|
|
1916
1934
|
# render_plotly and a Save of the same resolve reuse it.
|
|
1917
|
-
target = at_size(
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
"
|
|
1932
|
-
"
|
|
1933
|
-
"
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1935
|
+
target = at_size(
|
|
1936
|
+
settle(
|
|
1937
|
+
resolved,
|
|
1938
|
+
width_in=width,
|
|
1939
|
+
height_in=height,
|
|
1940
|
+
measure=measure if reusable else None,
|
|
1941
|
+
),
|
|
1942
|
+
width,
|
|
1943
|
+
height,
|
|
1944
|
+
)
|
|
1945
|
+
auto = target.auto_text
|
|
1946
|
+
decisions = trials.get(auto.reference) if auto is not None else None
|
|
1947
|
+
if decisions is not None:
|
|
1948
|
+
Log.info(
|
|
1949
|
+
"layout_decisions%s: kept the %gpt auto-size trial's layout "
|
|
1950
|
+
"(%d trial(s)); no second matplotlib layout",
|
|
1951
|
+
f" ({resolved.figure_label})" if resolved.figure_label else "",
|
|
1952
|
+
auto.reference,
|
|
1953
|
+
len(trials),
|
|
1954
|
+
layer=LAYER,
|
|
1955
|
+
)
|
|
1956
|
+
else:
|
|
1957
|
+
# Why a full draw: a fixed text size, a memo hit (the search did
|
|
1958
|
+
# not run here), or a custom kind.
|
|
1959
|
+
Log.debug(
|
|
1960
|
+
"layout_decisions: drawing (%s)",
|
|
1961
|
+
"custom kind" if not reusable
|
|
1962
|
+
else "fixed text size" if auto is None
|
|
1963
|
+
else "auto size reused, no trial here",
|
|
1964
|
+
layer=LAYER,
|
|
1965
|
+
)
|
|
1966
|
+
fig = render(target)
|
|
1967
|
+
try:
|
|
1968
|
+
decisions = _figure_decisions(fig)
|
|
1969
|
+
finally:
|
|
1970
|
+
plt.close(fig)
|
|
1971
|
+
return {
|
|
1972
|
+
**decisions,
|
|
1973
|
+
# autosize.AutoTextSize, or None when the size is fixed: the
|
|
1974
|
+
# preview draws at these sizes rather than searching again.
|
|
1975
|
+
"auto_text": auto,
|
|
1976
|
+
"width_in": width,
|
|
1977
|
+
"height_in": height,
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
|
|
1981
|
+
def _figure_decisions(fig) -> dict:
|
|
1982
|
+
"""What a drawn export decided, as ``layout_decisions`` returns it (less
|
|
1983
|
+
the size and ``auto_text``). The one reader of the figure's records, for
|
|
1984
|
+
both the final draw and a kept auto-size trial."""
|
|
1985
|
+
fits = getattr(fig, LABEL_FIT_ATTR, None) or {}
|
|
1986
|
+
axis_text = getattr(fig, AXIS_TEXT_ATTR, None) or ()
|
|
1987
|
+
return {
|
|
1988
|
+
"ticks": fits.get("ticks"),
|
|
1989
|
+
"brackets": fits.get("brackets"),
|
|
1990
|
+
"bracket_geometry": fits.get("bracket_geometry"),
|
|
1991
|
+
"grid_reach": getattr(fig, GRID_REACH_ATTR, None),
|
|
1992
|
+
# tuple[base.AxisText, ...]: the tick values/labels and title
|
|
1993
|
+
# distance the export drew, which the preview copies so the
|
|
1994
|
+
# y text it puts in a column gap is the text measured for it,
|
|
1995
|
+
# and a numeric x axis shows the ticks the auto size judged.
|
|
1996
|
+
"y_axes": tuple(a for a in axis_text if a.axis == "y"),
|
|
1997
|
+
"x_axes": tuple(a for a in axis_text if a.axis == "x"),
|
|
1998
|
+
"legend": getattr(fig, LEGEND_ATTR, None),
|
|
1999
|
+
# diffbars.FigurePlacement, or None: the preview draws these
|
|
2000
|
+
# bars and ranges rather than placing its own.
|
|
2001
|
+
"difference_bars": getattr(fig, DIFF_BARS_ATTR, None),
|
|
2002
|
+
}
|
|
1945
2003
|
|
|
1946
2004
|
|
|
1947
2005
|
def layout_report(resolved: ResolvedPlot):
|
|
@@ -1953,7 +2011,10 @@ def layout_report(resolved: ResolvedPlot):
|
|
|
1953
2011
|
return _layout_report(resolved)
|
|
1954
2012
|
|
|
1955
2013
|
|
|
1956
|
-
def _layout_report(resolved: ResolvedPlot):
|
|
2014
|
+
def _layout_report(resolved: ResolvedPlot, *, decisions_out: dict | None = None):
|
|
2015
|
+
"""``layout_report``'s body. ``decisions_out``, when given, is filled
|
|
2016
|
+
with the figure's ``_figure_decisions`` before it closes, so a trial at
|
|
2017
|
+
the chosen reference serves as the final layout too."""
|
|
1957
2018
|
import matplotlib.pyplot as plt
|
|
1958
2019
|
|
|
1959
2020
|
from ..autosize import LayoutReport
|
|
@@ -1964,6 +2025,8 @@ def _layout_report(resolved: ResolvedPlot):
|
|
|
1964
2025
|
with measuring():
|
|
1965
2026
|
fig = render(resolved)
|
|
1966
2027
|
try:
|
|
2028
|
+
if decisions_out is not None:
|
|
2029
|
+
decisions_out.update(_figure_decisions(fig))
|
|
1967
2030
|
fits = getattr(fig, LABEL_FIT_ATTR, None) or {}
|
|
1968
2031
|
ticks, brackets = fits.get("ticks"), fits.get("brackets")
|
|
1969
2032
|
legend = getattr(fig, LEGEND_ATTR, None) or {}
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|