scistackstatsdb 0.1.41__py3-none-any.whl
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.
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
scistackstatsdb — scidb-backed statistics.
|
|
3
|
+
|
|
4
|
+
Loads StatStudio tables from a scidb database through scistackplotdb's
|
|
5
|
+
``ScidbSource`` (the same loading the figures use), saves stats tables and
|
|
6
|
+
stats presets (``saved``), finds the stats tables linked to a saved plot, and
|
|
7
|
+
carries them in project bundles (``bundle_section``). The statistics
|
|
8
|
+
themselves are :mod:`scistackstats`.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from scistackstats import StatsSpec, load_tables
|
|
16
|
+
|
|
17
|
+
from .endpoint import StatsEndpointCode, generate_stats_endpoint, required_declarations
|
|
18
|
+
from .saved import (
|
|
19
|
+
SavedStats,
|
|
20
|
+
SavedStatsError,
|
|
21
|
+
SavedStatsExists,
|
|
22
|
+
SavedStatsInfo,
|
|
23
|
+
StatsPresetInfo,
|
|
24
|
+
apply_stats_preset,
|
|
25
|
+
find_saved_stats,
|
|
26
|
+
hide_saved_stats,
|
|
27
|
+
hide_stats_preset,
|
|
28
|
+
linked_stats_for,
|
|
29
|
+
list_saved_stats,
|
|
30
|
+
list_stats_presets,
|
|
31
|
+
load_saved_stats,
|
|
32
|
+
rename_saved_stats,
|
|
33
|
+
rename_stats_preset,
|
|
34
|
+
save_stats,
|
|
35
|
+
save_stats_preset,
|
|
36
|
+
saved_stats_history,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_stats_tables(db: Any, stats_spec: StatsSpec) -> dict:
|
|
41
|
+
"""``{variable: LongTable}`` for every DV of ``stats_spec``, from ``db``."""
|
|
42
|
+
from scistackplotdb import ScidbSource
|
|
43
|
+
|
|
44
|
+
return load_tables(ScidbSource(db), stats_spec)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
__all__ = [
|
|
48
|
+
"StatsEndpointCode", "generate_stats_endpoint", "required_declarations",
|
|
49
|
+
"SavedStats", "SavedStatsError", "SavedStatsExists", "SavedStatsInfo", "StatsPresetInfo",
|
|
50
|
+
"apply_stats_preset", "find_saved_stats", "hide_saved_stats", "hide_stats_preset", "linked_stats_for",
|
|
51
|
+
"list_saved_stats", "list_stats_presets", "load_saved_stats", "load_stats_tables", "rename_saved_stats",
|
|
52
|
+
"rename_stats_preset", "save_stats", "save_stats_preset", "saved_stats_history",
|
|
53
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""The ``stats`` section of a project bundle: saved stats tables and stats
|
|
2
|
+
presets, copied row for row (``VersionedStore.dump_rows`` / ``load_rows``),
|
|
3
|
+
like scistackplotdb's ``plots`` section. A schema-key rename is applied with
|
|
4
|
+
the same exact-string remap the plots section uses."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
from scistacklog import Log
|
|
11
|
+
from scistackplotdb.bundle_section import _remap_row
|
|
12
|
+
|
|
13
|
+
from .saved import PRESET_STORE, STORE
|
|
14
|
+
|
|
15
|
+
LAYER = "scistackstatsdb"
|
|
16
|
+
|
|
17
|
+
_STORES = {"saved_stats.json": STORE, "stats_presets.json": PRESET_STORE}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class StatsSection:
|
|
21
|
+
name = "stats"
|
|
22
|
+
|
|
23
|
+
def export(self, ctx) -> "dict[str, bytes]":
|
|
24
|
+
files: dict[str, bytes] = {}
|
|
25
|
+
for filename, store in _STORES.items():
|
|
26
|
+
rows = store.dump_rows(ctx.db)
|
|
27
|
+
if rows:
|
|
28
|
+
files[filename] = json.dumps(rows, indent=2, default=str).encode("utf-8")
|
|
29
|
+
Log.info("[bundle_section] stats export: %s", sorted(files), layer=LAYER)
|
|
30
|
+
return files
|
|
31
|
+
|
|
32
|
+
def import_(self, ctx, files: "dict[str, bytes]") -> dict:
|
|
33
|
+
report = {}
|
|
34
|
+
key_map = getattr(ctx, "key_map", None)
|
|
35
|
+
for filename, store in _STORES.items():
|
|
36
|
+
if filename in files:
|
|
37
|
+
rows = json.loads(files[filename].decode("utf-8"))
|
|
38
|
+
if key_map is not None and not key_map.is_identity:
|
|
39
|
+
rows = [_remap_row(row, store, key_map, ctx.map_report) for row in rows]
|
|
40
|
+
report[store.table] = store.load_rows(ctx.db, rows)
|
|
41
|
+
Log.info("[bundle_section] stats import: %s", report, layer=LAYER)
|
|
42
|
+
return report
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""StatStudio → pipeline: the ``stat_`` function plus its ``for_each`` call.
|
|
2
|
+
|
|
3
|
+
The function is ``scistackstats.codegen.generate_stats_function``. This
|
|
4
|
+
module writes the call around it:
|
|
5
|
+
|
|
6
|
+
- **no iteration keywords** (P7): one call over the whole fan-out, so a
|
|
7
|
+
correction family that spans strata or DVs is computed in one place. scidb
|
|
8
|
+
stores one record per call (a grand aggregation);
|
|
9
|
+
- one input per DV variable, loaded by name;
|
|
10
|
+
- ``finalized`` (record mode) by default, so the result is a lineage record
|
|
11
|
+
that goes stale when its inputs change and that ``scidb report`` lists.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from dataclasses import dataclass, field
|
|
17
|
+
|
|
18
|
+
from scistacklog import Log
|
|
19
|
+
from scistackplot import LongTable
|
|
20
|
+
|
|
21
|
+
from scistackstats import StatsSpec
|
|
22
|
+
from scistackstats.codegen import generate_stats_function
|
|
23
|
+
|
|
24
|
+
LAYER = "scistackstatsdb"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class StatsEndpointCode:
|
|
29
|
+
function_name: str
|
|
30
|
+
function_source: str
|
|
31
|
+
foreach_source: str
|
|
32
|
+
output_variable: str
|
|
33
|
+
inputs: dict[str, str] = field(default_factory=dict)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def source(self) -> str:
|
|
37
|
+
return f"{self.function_source}\n\n{self.foreach_source}"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def default_output_variable(stats_spec: StatsSpec) -> str:
|
|
41
|
+
"""``Ratings`` -> ``RatingsStats``."""
|
|
42
|
+
return f"{stats_spec.targets[0].variable}Stats"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def generate_stats_endpoint(
|
|
46
|
+
stats_spec: StatsSpec,
|
|
47
|
+
tables: dict[str, LongTable],
|
|
48
|
+
*,
|
|
49
|
+
function_name: str | None = None,
|
|
50
|
+
output_variable: str | None = None,
|
|
51
|
+
finalized: bool = True,
|
|
52
|
+
) -> StatsEndpointCode:
|
|
53
|
+
"""The ``stat_`` function and its ``for_each`` call. Raises
|
|
54
|
+
``scistackstats.codegen.NotExportable`` with the reason when the spec
|
|
55
|
+
cannot be exported yet."""
|
|
56
|
+
fn = generate_stats_function(stats_spec, tables, function_name=function_name)
|
|
57
|
+
output = output_variable or default_output_variable(stats_spec)
|
|
58
|
+
lines = ["for_each(", f" {fn.name},", " inputs={"]
|
|
59
|
+
lines += [f' "{param}": {variable},' for param, variable in fn.inputs.items()]
|
|
60
|
+
lines += [
|
|
61
|
+
" },",
|
|
62
|
+
f" outputs=[{output}],",
|
|
63
|
+
f" as_table={list(fn.inputs)!r},",
|
|
64
|
+
f" finalized={finalized},",
|
|
65
|
+
")",
|
|
66
|
+
]
|
|
67
|
+
Log.info("[stats endpoint] %s: inputs %s -> %s, finalized=%s (no iteration: one record)",
|
|
68
|
+
fn.name, fn.inputs, output, finalized, layer=LAYER)
|
|
69
|
+
return StatsEndpointCode(function_name=fn.name, function_source=fn.source,
|
|
70
|
+
foreach_source="\n".join(lines), output_variable=output, inputs=fn.inputs)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def required_declarations(code: StatsEndpointCode) -> list[str]:
|
|
74
|
+
"""Variable types the call needs that may not exist yet (the output)."""
|
|
75
|
+
return [code.output_variable]
|
scistackstatsdb/saved.py
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""Saved StatStudio tables and stats presets, kept in the project database.
|
|
2
|
+
|
|
3
|
+
Both use scistackplotdb's :class:`~scistackplotdb._versioned.VersionedStore`,
|
|
4
|
+
the owner of the saved-plot rules (S20). So a saved stats table behaves like
|
|
5
|
+
a saved plot:
|
|
6
|
+
|
|
7
|
+
- the id is the identity, the name a label, unique across the project;
|
|
8
|
+
- re-saving a visible name appends a version, and the newest version opens;
|
|
9
|
+
- "remove" hides every version, and nothing is ever deleted;
|
|
10
|
+
- save is strict (``StatsSpec.from_dict``), open salvages
|
|
11
|
+
(``scistackstats.restore``), and opening never rewrites the stored copy.
|
|
12
|
+
|
|
13
|
+
A saved stats table may name the saved plot it syncs with
|
|
14
|
+
(``StatsSpec.linked_plot``, S11). The link is stored only here.
|
|
15
|
+
:func:`linked_stats_for` finds a plot's stats tables by query, so the plot
|
|
16
|
+
store never holds a back-reference.
|
|
17
|
+
|
|
18
|
+
A **stats preset** stores only the stats settings
|
|
19
|
+
(``scistackstats.restore.STATS_SETTINGS``): what to compute and how it reads.
|
|
20
|
+
Applying one to a stats table keeps that table's design, DVs and link.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from dataclasses import dataclass, field
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
from scistacklog import Log
|
|
29
|
+
from scistackplotdb._versioned import VersionedStore
|
|
30
|
+
|
|
31
|
+
from scistackstats import StatsSpec, StatsSpecError
|
|
32
|
+
from scistackstats.restore import restore_stats_spec, stats_settings, with_stats_settings
|
|
33
|
+
|
|
34
|
+
LAYER = "scistackstatsdb"
|
|
35
|
+
ENVELOPE_FORMAT = 1
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SavedStatsError(ValueError):
|
|
39
|
+
"""A save, rename or load that cannot be done as asked."""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SavedStatsExists(SavedStatsError):
|
|
43
|
+
"""``save_stats(overwrite=False)`` found another visible item with that name."""
|
|
44
|
+
|
|
45
|
+
def __init__(self, existing: "SavedStatsInfo"):
|
|
46
|
+
super().__init__(f"There is already a saved stats table named {existing.name!r} (version {existing.version}).")
|
|
47
|
+
self.existing = existing
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
STORE = VersionedStore(
|
|
51
|
+
table="_stats_spec", id_column="stats_id", scope_column=None,
|
|
52
|
+
noun="saved stats table", tag="saved-stats", error=SavedStatsError,
|
|
53
|
+
)
|
|
54
|
+
PRESET_STORE = VersionedStore(
|
|
55
|
+
table="_stats_preset", id_column="preset_id", scope_column=None,
|
|
56
|
+
noun="stats preset", tag="stats-preset", error=SavedStatsError,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class SavedStatsInfo:
|
|
62
|
+
stats_id: str
|
|
63
|
+
name: str
|
|
64
|
+
version: int
|
|
65
|
+
saved_at: str
|
|
66
|
+
hidden: bool = False
|
|
67
|
+
linked_plot: str | None = None
|
|
68
|
+
dvs: tuple[str, ...] = ()
|
|
69
|
+
|
|
70
|
+
def to_dict(self) -> dict[str, Any]:
|
|
71
|
+
return {"stats_id": self.stats_id, "name": self.name, "version": self.version, "saved_at": self.saved_at,
|
|
72
|
+
"hidden": self.hidden, "linked_plot": self.linked_plot, "dvs": list(self.dvs)}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class SavedStats:
|
|
77
|
+
info: SavedStatsInfo
|
|
78
|
+
spec: StatsSpec
|
|
79
|
+
#: Settings that did not come back as saved (``RestoreNote`` dicts).
|
|
80
|
+
notes: list[dict[str, Any]] = field(default_factory=list)
|
|
81
|
+
stored_format: Any = None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _versions() -> dict[str, str]:
|
|
85
|
+
import scistackstats
|
|
86
|
+
from scistackstats import get_engine
|
|
87
|
+
|
|
88
|
+
out = {"scistackstats": getattr(scistackstats, "__version__", "dev")}
|
|
89
|
+
try:
|
|
90
|
+
out.update(get_engine().versions())
|
|
91
|
+
except Exception: # pragma: no cover - versions are display only
|
|
92
|
+
pass
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _strict(spec: Any) -> StatsSpec:
|
|
97
|
+
if isinstance(spec, StatsSpec):
|
|
98
|
+
return spec
|
|
99
|
+
try:
|
|
100
|
+
return StatsSpec.from_dict(spec)
|
|
101
|
+
except (StatsSpecError, KeyError, TypeError, ValueError) as exc:
|
|
102
|
+
raise SavedStatsError(f"The stats settings could not be read: {exc}") from exc
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _info(row, envelope: dict | None = None) -> SavedStatsInfo:
|
|
106
|
+
stats_id, _scope, name, version, saved_at, hidden = row
|
|
107
|
+
envelope = envelope or {}
|
|
108
|
+
linked = envelope.get("linked_plot")
|
|
109
|
+
dvs = envelope.get("dvs")
|
|
110
|
+
return SavedStatsInfo(
|
|
111
|
+
stats_id=str(stats_id), name=str(name), version=int(version), saved_at=str(saved_at), hidden=bool(hidden),
|
|
112
|
+
linked_plot=linked if isinstance(linked, str) else None,
|
|
113
|
+
dvs=tuple(str(d) for d in dvs) if isinstance(dvs, list) else (),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _newest(db, stats_id: str) -> SavedStatsInfo:
|
|
118
|
+
row, text = STORE.load(db, stats_id)
|
|
119
|
+
return _info(row, STORE.parse_envelope(text, f"{row[2]!r} version {row[3]}"))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def save_stats(db, name: str, spec: Any, *, overwrite: bool = True, current_stats_id: str | None = None) -> SavedStatsInfo:
|
|
123
|
+
"""Save a stats spec (or its dict, read strictly) as *name*."""
|
|
124
|
+
name = STORE.check_name(name)
|
|
125
|
+
spec = _strict(spec)
|
|
126
|
+
envelope = {
|
|
127
|
+
"format": ENVELOPE_FORMAT,
|
|
128
|
+
"spec": spec.to_dict(),
|
|
129
|
+
"linked_plot": spec.linked_plot,
|
|
130
|
+
"dvs": [d.key for d in spec.targets],
|
|
131
|
+
"saved_with": _versions(),
|
|
132
|
+
}
|
|
133
|
+
row, _new = STORE.save(db, None, name, envelope, overwrite=overwrite, current_id=current_stats_id,
|
|
134
|
+
on_clash=lambda clash: SavedStatsExists(_info(clash)))
|
|
135
|
+
return _info(row, envelope)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def load_saved_stats(db, stats_id: str, *, version: int | None = None) -> SavedStats:
|
|
139
|
+
"""One version (the newest by default), salvaged. Never rewrites it."""
|
|
140
|
+
row, text = STORE.load(db, stats_id, version)
|
|
141
|
+
envelope = STORE.parse_envelope(text, f"{row[2]!r} version {row[3]}")
|
|
142
|
+
info = _info(row, envelope)
|
|
143
|
+
restored = restore_stats_spec(envelope.get("spec"), fallback_measure=(info.dvs[0].split("[")[0] if info.dvs else None))
|
|
144
|
+
Log.info("[saved-stats] opened %r version %d (envelope format %r): %d note(s)",
|
|
145
|
+
info.name, info.version, envelope.get("format"), len(restored.notes), layer=LAYER)
|
|
146
|
+
return SavedStats(info=info, spec=restored.spec, notes=[n.to_dict() for n in restored.notes],
|
|
147
|
+
stored_format=envelope.get("format"))
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def list_saved_stats(db, *, include_hidden: bool = False) -> list[SavedStatsInfo]:
|
|
151
|
+
return [_info(row[:6], STORE.parse_envelope(row[6], repr(row[2])))
|
|
152
|
+
for row in STORE.list_rows(db, include_hidden=include_hidden, with_envelope=True)]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def saved_stats_history(db, stats_id: str) -> list[SavedStatsInfo]:
|
|
156
|
+
return [_info(row[:6], STORE.parse_envelope(row[6], repr(row[2])))
|
|
157
|
+
for row in STORE.history(db, stats_id, with_envelope=True)]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def rename_saved_stats(db, stats_id: str, new_name: str) -> SavedStatsInfo:
|
|
161
|
+
STORE.rename(db, stats_id, new_name)
|
|
162
|
+
return _newest(db, stats_id)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def hide_saved_stats(db, stats_id: str, hidden: bool = True) -> SavedStatsInfo:
|
|
166
|
+
STORE.set_hidden(db, stats_id, hidden)
|
|
167
|
+
return _newest(db, stats_id)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def linked_stats_for(db, saved_plot_id: str) -> list[SavedStatsInfo]:
|
|
171
|
+
"""The visible saved stats tables linked to one saved plot (S11)."""
|
|
172
|
+
found = [info for info in list_saved_stats(db) if info.linked_plot == saved_plot_id]
|
|
173
|
+
Log.debug("[saved-stats] plot %s: %d linked stats table(s)", saved_plot_id, len(found), layer=LAYER)
|
|
174
|
+
return found
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def find_saved_stats(db, name: str) -> SavedStatsInfo | None:
|
|
178
|
+
row = STORE.visible_by_name(db, None, STORE.check_name(name))
|
|
179
|
+
return _newest(db, row[0]) if row else None
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
# Stats presets
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@dataclass(frozen=True)
|
|
188
|
+
class StatsPresetInfo:
|
|
189
|
+
preset_id: str
|
|
190
|
+
name: str
|
|
191
|
+
version: int
|
|
192
|
+
saved_at: str
|
|
193
|
+
hidden: bool = False
|
|
194
|
+
|
|
195
|
+
def to_dict(self) -> dict[str, Any]:
|
|
196
|
+
return dict(self.__dict__)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _preset_info(row) -> StatsPresetInfo:
|
|
200
|
+
preset_id, _scope, name, version, saved_at, hidden = row[:6]
|
|
201
|
+
return StatsPresetInfo(str(preset_id), str(name), int(version), str(saved_at), bool(hidden))
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def save_stats_preset(db, name: str, spec: Any, *, overwrite: bool = True,
|
|
205
|
+
current_preset_id: str | None = None) -> StatsPresetInfo:
|
|
206
|
+
"""Save *spec*'s stats settings (no design, DVs or link) as a preset."""
|
|
207
|
+
name = PRESET_STORE.check_name(name)
|
|
208
|
+
spec = _strict(spec)
|
|
209
|
+
envelope = {"format": ENVELOPE_FORMAT, "settings": stats_settings(spec), "saved_with": _versions()}
|
|
210
|
+
row, _ = PRESET_STORE.save(db, None, name, envelope, overwrite=overwrite, current_id=current_preset_id,
|
|
211
|
+
on_clash=lambda clash: SavedStatsError(PRESET_STORE.clash_message(None, name)))
|
|
212
|
+
return _preset_info(row)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def list_stats_presets(db, *, include_hidden: bool = False) -> list[StatsPresetInfo]:
|
|
216
|
+
return [_preset_info(row) for row in PRESET_STORE.list_rows(db, include_hidden=include_hidden)]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def hide_stats_preset(db, preset_id: str, hidden: bool = True) -> StatsPresetInfo:
|
|
220
|
+
PRESET_STORE.set_hidden(db, preset_id, hidden)
|
|
221
|
+
return _preset_info(PRESET_STORE.latest(db, preset_id))
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def rename_stats_preset(db, preset_id: str, new_name: str) -> StatsPresetInfo:
|
|
225
|
+
PRESET_STORE.rename(db, preset_id, new_name)
|
|
226
|
+
return _preset_info(PRESET_STORE.latest(db, preset_id))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def apply_stats_preset(db, preset_id: str, target: StatsSpec, *, version: int | None = None) -> tuple[StatsSpec, list[dict]]:
|
|
230
|
+
"""``target`` with the preset's stats settings; its design, DVs and link kept."""
|
|
231
|
+
row, text = PRESET_STORE.load(db, preset_id, version)
|
|
232
|
+
envelope = PRESET_STORE.parse_envelope(text, f"{row[2]!r} version {row[3]}")
|
|
233
|
+
spec, notes = with_stats_settings(target, envelope.get("settings") or {})
|
|
234
|
+
Log.info("[stats-preset] %r version %d applied to %s: %d note(s)", row[2], row[3],
|
|
235
|
+
", ".join(d.key for d in target.targets), len(notes), layer=LAYER)
|
|
236
|
+
return spec, [n.to_dict() for n in notes]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: scistackstatsdb
|
|
3
|
+
Version: 0.1.41
|
|
4
|
+
Summary: scidb-backed statistics: saved StatStudio specs, linked plots and stat_ endpoints
|
|
5
|
+
Author: SciStack Contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: provenance,scidb,scistack,statistics,visualization
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: scistack-db==0.1.41
|
|
21
|
+
Requires-Dist: scistacklog==0.1.41
|
|
22
|
+
Requires-Dist: scistackplot==0.1.41
|
|
23
|
+
Requires-Dist: scistackplotdb==0.1.41
|
|
24
|
+
Requires-Dist: scistackstats==0.1.41
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# scistackstatsdb
|
|
31
|
+
|
|
32
|
+
scidb-backed statistics: loads StatStudio tables through `scistackplotdb`,
|
|
33
|
+
and (later stages) saved stats specs, linked plots and `stat_` endpoints.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
scistackstatsdb/__init__.py,sha256=vSFSco9f32gpwMj5eJYyToaGdDZOf16K2X2h7IVd2rs,1730
|
|
2
|
+
scistackstatsdb/bundle_section.py,sha256=q9tu5LU5_t6wGsEBlKbi9y5cbshMbWiLGvh-CVRAvnY,1596
|
|
3
|
+
scistackstatsdb/endpoint.py,sha256=KCfEwfHQ1PaSVZBTT8OgWPjtXJB_zcJFNEqTGa2Ysb0,2701
|
|
4
|
+
scistackstatsdb/saved.py,sha256=WVizvvVXjRpA_BDRDewKvdANWtXK0VnyojQliv5i8iY,9425
|
|
5
|
+
scistackstatsdb-0.1.41.dist-info/METADATA,sha256=-OIfT0T0VNY7_kSh1LBwklpfHSulsURqKys7VX2ihPw,1329
|
|
6
|
+
scistackstatsdb-0.1.41.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
7
|
+
scistackstatsdb-0.1.41.dist-info/RECORD,,
|