rosetta-eclab 0.1.1__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.
File without changes
rosetta_eclab/cli.py ADDED
@@ -0,0 +1,113 @@
1
+ """rosetta: name the columns of a BioLogic EC-Lab .mpr file that your parser does not know.
2
+
3
+ rosetta FILE.mpr # name every column unknown to galvani (default reference parser)
4
+ rosetta FILE.mpr --reference yadg # ... unknown to yadg instead
5
+ rosetta FILE.mpr --self-check # also hide each known column in turn and report how many come back right
6
+ rosetta FILE.mpr --json # machine-readable output
7
+
8
+ No language model and no network access: names come from physical relations,
9
+ storage types and column shapes (namer/library.py), with a statistics fallback.
10
+ Every answer carries its evidence; "ABSTAIN" means the data does not support a name.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import json
17
+ import sys
18
+ import warnings
19
+
20
+ from spike2 import vocab
21
+
22
+ from . import mprfile
23
+ from .evaluate import answer
24
+
25
+
26
+ def unit_of(name: str) -> str:
27
+ e = next((v for v in vocab.vocabulary() if v["name"] == name), None)
28
+ return " or ".join(e["units"]) if e and e["units"] else ""
29
+
30
+
31
+ def own_group(path: str) -> str | None:
32
+ """If the file is one of the public files behind the statistics table, leave its group out (no self-matches)."""
33
+ from pathlib import Path
34
+
35
+ from spike2 import corpus
36
+
37
+ return corpus.source_group(Path(path).name)
38
+
39
+
40
+ def name_unknown(m: mprfile.MprData) -> list[dict]:
41
+ known = [c for c in m.columns if c.known]
42
+ out = []
43
+ for c in m.unknown:
44
+ a = answer(c.values, c.dtype, known, m.technique, vocab.names(), exclude_group=own_group(m.path))
45
+ out.append({"column_id": c.raw_id, "dtype": c.dtype, "verdict": a["verdict"], "name": a.get("name"),
46
+ "unit": unit_of(a["name"]) if a["verdict"] == "NAME" else "", "confidence": a.get("confidence"),
47
+ "duplicate_of": a.get("duplicate_of", ""), "alternatives": a.get("alternatives", []),
48
+ "evidence": a.get("evidence", "")})
49
+ return out
50
+
51
+
52
+ def self_check(m: mprfile.MprData) -> dict:
53
+ known = [c for c in m.columns if c.known]
54
+ rows = []
55
+ for c in known:
56
+ others = [o for o in known if o is not c]
57
+ a = answer(c.values, c.dtype, others, m.technique, vocab.names(), exclude_group=own_group(m.path))
58
+ rows.append({"column": c.name, "verdict": a["verdict"], "answer": a.get("name"),
59
+ "correct": a["verdict"] == "NAME" and a.get("name") == vocab.canonical(c.name)})
60
+ named = [r for r in rows if r["verdict"] == "NAME"]
61
+ return {"hidden_one_at_a_time": len(rows), "named": len(named), "named_correctly": sum(r["correct"] for r in rows),
62
+ "wrong": [r for r in named if not r["correct"]], "rows": rows}
63
+
64
+
65
+ def main(argv: list[str] | None = None) -> int:
66
+ warnings.filterwarnings("ignore")
67
+ sys.stdout.reconfigure(encoding="utf-8")
68
+ ap = argparse.ArgumentParser(prog="rosetta", description=__doc__.splitlines()[0])
69
+ ap.add_argument("file")
70
+ ap.add_argument("--reference", choices=["galvani", "yadg"], default="galvani",
71
+ help="parser whose column map defines 'known' (default: galvani)")
72
+ ap.add_argument("--self-check", action="store_true", help="hide each known column in turn and try to name it")
73
+ ap.add_argument("--json", action="store_true")
74
+ a = ap.parse_args(argv)
75
+ try:
76
+ m = mprfile.read(a.file, a.reference)
77
+ except Exception as exc:
78
+ print(f"rosetta: {exc}", file=sys.stderr)
79
+ return 2
80
+ result = {"file": a.file, "technique": m.technique, "rows": m.n_points, "record_bytes": m.record_size,
81
+ "notes": m.notes, "unknown_columns": name_unknown(m)}
82
+ if a.self_check:
83
+ result["self_check"] = self_check(m)
84
+ if a.json:
85
+ print(json.dumps(result, indent=1, ensure_ascii=False, default=float))
86
+ return 0
87
+ print(f"{a.file}\n technique {m.technique or 'unknown'}, {m.n_points} rows, {m.record_size} bytes per record")
88
+ for n in m.notes:
89
+ print(f" {n}")
90
+ if not result["unknown_columns"]:
91
+ print(f" every column is known to {a.reference}; nothing to name")
92
+ for u in result["unknown_columns"]:
93
+ if u["verdict"] == "NAME":
94
+ head = f"{u['name']} [{u['unit'] or 'no unit'}] (confidence {u['confidence']})"
95
+ elif u["verdict"] == "DUPLICATE":
96
+ head = f"DUPLICATE of {u['duplicate_of']} (identical in every row)"
97
+ else:
98
+ head = "ABSTAIN (the data does not support a name)"
99
+ print(f"\n column ID {u['column_id']} ({u['dtype']}): {head}")
100
+ print(f" evidence: {u['evidence']}")
101
+ if u["alternatives"]:
102
+ print(f" also considered: {', '.join(u['alternatives'])}")
103
+ if a.self_check:
104
+ s = result["self_check"]
105
+ print(f"\n self-check: hid each of {s['hidden_one_at_a_time']} known columns in turn; named {s['named']}, "
106
+ f"{s['named_correctly']} correctly, {len(s['wrong'])} wrong, the rest abstained")
107
+ for w in s["wrong"]:
108
+ print(f" wrong: {w['column']} -> {w['answer']}")
109
+ return 0
110
+
111
+
112
+ if __name__ == "__main__":
113
+ raise SystemExit(main())
@@ -0,0 +1 @@
1
+ {"rows": [["bcd.issue_241.mpr", "BCD", "time"], ["bcd.issue_241.mpr", "BCD", "control"], ["bcd.issue_241.mpr", "BCD", "Ewe"], ["bcd.issue_241.mpr", "BCD", "I"], ["bcd.issue_241.mpr", "BCD", "dq"], ["bcd.issue_241.mpr", "BCD", "(Q-Qo)"], ["bcd.issue_241.mpr", "BCD", "I Range"], ["bcd.issue_241.mpr", "BCD", "Q charge or discharge"], ["bcd.issue_241.mpr", "BCD", "half cycle"], ["bio_logic", null, "time"], ["bio_logic", null, "Ewe"], ["bio_logic", null, "Ns"], ["bio_logic", null, "time"], ["bio_logic", null, "control"], ["bio_logic", null, "Ewe"], ["bio_logic", null, "dq"], ["bio_logic", null, "Pwe"], ["bio_logic", null, "time"], ["bio_logic", null, "control"], ["bio_logic", null, "Ewe"], ["bio_logic", null, "I"], ["bio_logic", null, "dQ"], ["bio_logic", null, "Pwe"], ["bio_logic", null, "time"], ["bio_logic", null, "control"], ["bio_logic", null, "Ewe"], ["bio_logic", null, "I"], ["bio_logic", null, "cycle number"], ["bio_logic", null, "(Q-Qo)"], ["ca.issue_134.mpr", "CA", "time"], ["ca.issue_134.mpr", "CA", "Ewe"], ["ca.issue_134.mpr", "CA", "I"], ["ca.issue_134.mpr", "CA", "(Q-Qo)"], ["ca.issue_134.mpr", "CA", "dQ"], ["ca.issue_134.mpr", "CA", "Q charge or discharge"], ["ca.issue_134.mpr", "CA", "half cycle"], ["ca.issue_134.mpr", "CA", "Capacitance charge"], ["issue_149", "CA", "time"], ["issue_149", "CA", "control"], ["issue_149", "CA", "Ewe"], ["issue_149", "CA", "I"], ["issue_149", "CA", "dQ"], ["issue_149", "CA", "(Q-Qo)"], ["issue_149", "CA", "I Range"], ["issue_149", "CA", "Q charge or discharge"], ["issue_149", "CA", "half cycle"], ["issue_149", "CA", "Pwe"], ["ca.mpr", "CA", "time"], ["ca.mpr", "CA", "Ewe"], ["ca.mpr", "CA", "I"], ["ca.mpr", "CA", "dQ"], ["ca.mpr", "CA", "(Q-Qo)"], ["ca.mpr", "CA", "I Range"], ["ca.mpr", "CA", "Q charge or discharge"], ["ca.mpr", "CA", "Energy we charge"], ["ca.mpr", "CA", "Capacitance charge"], ["issue_185", "coC", "time"], ["issue_185", "coC", "control"], ["issue_185", "coC", "Ewe"], ["issue_185", "coC", "I"], ["issue_185", "coC", "dq"], ["issue_185", "coC", "dQ"], ["issue_185", "coC", "(Q-Qo)"], ["issue_185", "coC", "I Range"], ["issue_185", "coC", "Q charge or discharge"], ["issue_185", "coC", "Energy we charge"], ["issue_185", "coC", "Capacitance charge"], ["issue_185", "coC", "step time"], ["issue_185", "coV", "time"], ["issue_185", "coV", "control"], ["issue_185", "coV", "Ewe"], ["issue_185", "coV", "I"], ["issue_185", "coV", "dQ"], ["issue_185", "coV", "dq"], ["issue_185", "coV", "(Q-Qo)"], ["issue_185", "coV", "I Range"], ["issue_185", "coV", "Q charge or discharge"], ["issue_185", "coV", "Energy we charge"], ["issue_185", "coV", "Capacitance charge"], ["issue_185", "coV", "step time"], ["issue_149", "CP", "time"], ["issue_149", "CP", "Ewe"], ["issue_149", "CP", "I"], ["issue_149", "CP", "dQ"], ["issue_149", "CP", "(Q-Qo)"], ["issue_149", "CP", "half cycle"], ["issue_149", "CP", "Q charge or discharge"], ["cp.issue_61.mpr", "CP", "Ns"], ["cp.issue_61.mpr", "CP", "time"], ["cp.issue_61.mpr", "CP", "control"], ["cp.issue_61.mpr", "CP", "Ewe"], ["cp.issue_61.mpr", "CP", "I"], ["cp.issue_61.mpr", "CP", "dQ"], ["cp.issue_61.mpr", "CP", "(Q-Qo)"], ["cp.issue_61.mpr", "CP", "Q charge or discharge"], ["cp.issue_61.mpr", "CP", "Energy we charge"], ["cp.issue_61.mpr", "CP", "Capacitance charge"], ["cp.mpr", "CP", "time"], ["cp.mpr", "CP", "Ewe"], ["cp.mpr", "CP", "I"], ["cp.mpr", "CP", "dQ"], ["cp.mpr", "CP", "(Q-Qo)"], ["cp.mpr", "CP", "Q charge or discharge"], ["cp.mpr", "CP", "Ece"], ["issue_149", "CV", "time"], ["issue_149", "CV", "control"], ["issue_149", "CV", "Ewe"], ["issue_149", "CV", "I"], ["issue_149", "CV", "cycle number"], ["issue_149", "CV", "(Q-Qo)"], ["issue_149", "CV", "I Range"], ["issue_149", "CV", "Rcmp"], ["issue_149", "CV", "step time"], ["cv.issue_217.mpr", "CV", "time"], ["cv.issue_217.mpr", "CV", "control"], ["cv.issue_217.mpr", "CV", "Ewe"], ["cv.issue_217.mpr", "CV", "I"], ["cv.issue_217.mpr", "CV", "cycle number"], ["cv.issue_217.mpr", "CV", "(Q-Qo)"], ["cv.issue_217.mpr", "CV", "I Range"], ["cv.issue_217.mpr", "CV", "Ece"], ["cv.issue_217.mpr", "CV", "Rcmp"], ["cv.mpr", "CV", "time"], ["cv.mpr", "CV", "control"], ["cv.mpr", "CV", "Ewe"], ["cv.mpr", "CV", "I"], ["cv.mpr", "CV", "cycle number"], ["cv.mpr", "CV", "(Q-Qo)"], ["cva.issue_135.mpr", "CVA", "time"], ["cva.issue_135.mpr", "CVA", "control"], ["cva.issue_135.mpr", "CVA", "Ewe"], ["cva.issue_135.mpr", "CVA", "I"], ["cva.issue_135.mpr", "CVA", "cycle number"], ["cva.issue_135.mpr", "CVA", "(Q-Qo)"], ["cva.issue_202.mpr", "CVA", "time"], ["cva.issue_202.mpr", "CVA", "control"], ["cva.issue_202.mpr", "CVA", "Ewe"], ["cva.issue_202.mpr", "CVA", "I"], ["cva.issue_202.mpr", "CVA", "(Q-Qo)"], ["issue_149", "GCPL", "Ns"], ["issue_149", "GCPL", "time"], ["issue_149", "GCPL", "dq"], ["issue_149", "GCPL", "(Q-Qo)"], ["issue_149", "GCPL", "control"], ["issue_149", "GCPL", "Ewe"], ["issue_149", "GCPL", "I Range"], ["issue_149", "GCPL", "Q charge or discharge"], ["issue_149", "GCPL", "half cycle"], ["issue_149", "GCPL", "Pwe"], ["gcpl.issue_175.mpr", "GCPL", "Ns"], ["gcpl.issue_175.mpr", "GCPL", "time"], ["gcpl.issue_175.mpr", "GCPL", "dq"], ["gcpl.issue_175.mpr", "GCPL", "(Q-Qo)"], ["gcpl.issue_175.mpr", "GCPL", "control"], ["gcpl.issue_175.mpr", "GCPL", "Ewe"], ["gcpl.issue_175.mpr", "GCPL", "I Range"], ["gcpl.issue_175.mpr", "GCPL", "Q charge or discharge"], ["gcpl.issue_175.mpr", "GCPL", "half cycle"], ["gcpl.issue_211.mpr", "GCPL", "Ns"], ["gcpl.issue_211.mpr", "GCPL", "time"], ["gcpl.issue_211.mpr", "GCPL", "dq"], ["gcpl.issue_211.mpr", "GCPL", "(Q-Qo)"], ["gcpl.issue_211.mpr", "GCPL", "control"], ["gcpl.issue_211.mpr", "GCPL", "Ewe"], ["gcpl.issue_211.mpr", "GCPL", "Ece"], ["gcpl.issue_211.mpr", "GCPL", "Q charge or discharge"], ["gcpl.issue_211.mpr", "GCPL", "half cycle"], ["gcpl.issue_211.mpr", "GCPL", "Energy we charge"], ["gcpl.issue_211.mpr", "GCPL", "Energy we discharge"], ["issue_226", "GCPL", "Ns"], ["issue_226", "GCPL", "time"], ["issue_226", "GCPL", "dq"], ["issue_226", "GCPL", "(Q-Qo)"], ["issue_226", "GCPL", "control"], ["issue_226", "GCPL", "Ewe"], ["issue_226", "GCPL", "Ece"], ["issue_226", "GCPL", "Q charge or discharge"], ["issue_226", "GCPL", "half cycle"], ["issue_226", "GCPL", "Ns"], ["issue_226", "GCPL", "time"], ["issue_226", "GCPL", "dq"], ["issue_226", "GCPL", "(Q-Qo)"], ["issue_226", "GCPL", "control"], ["issue_226", "GCPL", "Ewe"], ["issue_226", "GCPL", "Ece"], ["issue_226", "GCPL", "Q charge or discharge"], ["issue_226", "GCPL", "half cycle"], ["gcpl.issue_228.mpr", "GCPL", "Ns"], ["gcpl.issue_228.mpr", "GCPL", "time"], ["gcpl.issue_228.mpr", "GCPL", "dq"], ["gcpl.issue_228.mpr", "GCPL", "(Q-Qo)"], ["gcpl.issue_228.mpr", "GCPL", "control"], ["gcpl.issue_228.mpr", "GCPL", "Ewe"], ["gcpl.issue_228.mpr", "GCPL", "I Range"], ["gcpl.issue_228.mpr", "GCPL", "Q charge or discharge"], ["gcpl.issue_228.mpr", "GCPL", "half cycle"], ["gcpl.issue_228.mpr", "GCPL", "Pwe"], ["gcpl.issue_230.mpr", "GCPL", "Ns"], ["gcpl.issue_230.mpr", "GCPL", "time"], ["gcpl.issue_230.mpr", "GCPL", "dq"], ["gcpl.issue_230.mpr", "GCPL", "(Q-Qo)"], ["gcpl.issue_230.mpr", "GCPL", "control"], ["gcpl.issue_230.mpr", "GCPL", "Ewe"], ["gcpl.issue_230.mpr", "GCPL", "Ece"], ["gcpl.issue_230.mpr", "GCPL", "I Range"], ["gcpl.issue_230.mpr", "GCPL", "Q charge or discharge"], ["gcpl.issue_230.mpr", "GCPL", "half cycle"], ["gcpl.issue_230.mpr", "GCPL", "Analog IN 1"], ["gcpl.issue_230.mpr", "GCPL", "Energy we charge"], ["gcpl.issue_230.mpr", "GCPL", "Energy we discharge"], ["gcpl.issue_230.mpr", "GCPL", "Energy ce charge"], ["gcpl.issue_230.mpr", "GCPL", "Energy ce discharge"], ["gcpl.issue_230.mpr", "GCPL", "Capacitance charge"], ["gcpl.issue_230.mpr", "GCPL", "Capacitance discharge"], ["gcpl.issue_230.mpr", "GCPL", "step time"], ["gcpl.mpr", "GCPL", "Ns"], ["gcpl.mpr", "GCPL", "time"], ["gcpl.mpr", "GCPL", "dq"], ["gcpl.mpr", "GCPL", "(Q-Qo)"], ["gcpl.mpr", "GCPL", "control"], ["gcpl.mpr", "GCPL", "Ewe"], ["gcpl.mpr", "GCPL", "Q charge or discharge"], ["gcpl.mpr", "GCPL", "half cycle"], ["gcpl.mpr", "GCPL", "Energy we charge"], ["gcpl.mpr", "GCPL", "Energy we discharge"], ["gcpl.mpr", "GCPL", "Capacitance charge"], ["gcpl.mpr", "GCPL", "Capacitance discharge"], ["pr_182", "GCPL", "Ns"], ["pr_182", "GCPL", "time"], ["pr_182", "GCPL", "dq"], ["pr_182", "GCPL", "control"], ["pr_182", "GCPL", "Ewe"], ["pr_182", "GCPL", "I Range"], ["pr_182", "GCPL", "Ece"], ["pr_182", "GCPL", "Pwe"], ["pr_182", "GCPL", "Q charge or discharge"], ["pr_182", "GCPL", "half cycle"], ["pr_182", "GCPL", "(Q-Qo)"], ["pr_182", "GCPL", "Energy we charge"], ["pr_182", "GCPL", "Energy we discharge"], ["pr_182", "GCPL", "Capacitance charge"], ["pr_182", "GCPL", "Capacitance discharge"], ["pr_182", "GCPL", "Ns"], ["pr_182", "GCPL", "time"], ["pr_182", "GCPL", "dq"], ["pr_182", "GCPL", "control"], ["pr_182", "GCPL", "Ewe"], ["pr_182", "GCPL", "I Range"], ["pr_182", "GCPL", "Ece"], ["pr_182", "GCPL", "Pwe"], ["pr_182", "GCPL", "Q charge or discharge"], ["pr_182", "GCPL", "half cycle"], ["pr_182", "GCPL", "Energy we charge"], ["pr_182", "GCPL", "Energy we discharge"], ["pr_182", "GCPL", "Capacitance charge"], ["pr_182", "GCPL", "Capacitance discharge"], ["pr_182", "GCPL", "(Q-Qo)"], ["issue_149", "GEIS", "freq"], ["issue_149", "GEIS", "Re(Z)"], ["issue_149", "GEIS", "-Im(Z)"], ["issue_149", "GEIS", "|Z|"], ["issue_149", "GEIS", "Phase(Z)"], ["issue_149", "GEIS", "time"], ["issue_149", "GEIS", "Ewe"], ["issue_149", "GEIS", "I"], ["issue_149", "GEIS", "Cs"], ["issue_149", "GEIS", "Cp"], ["issue_149", "GEIS", "cycle number"], ["issue_149", "GEIS", "|Ewe|"], ["issue_149", "GEIS", "|I|"], ["issue_149", "GEIS", "(Q-Qo)"], ["issue_149", "GEIS", "Pwe"], ["issue_149", "GEIS", "THD Ewe"], ["issue_149", "GEIS", "NSD Ewe"], ["issue_149", "GEIS", "NSR Ewe"], ["issue_149", "GEIS", "|Ewe h2|"], ["issue_149", "GEIS", "|Ewe h3|"], ["issue_149", "GEIS", "|Ewe h4|"], ["issue_149", "GEIS", "|Ewe h5|"], ["issue_149", "GEIS", "|Ewe h6|"], ["issue_149", "GEIS", "|Ewe h7|"], ["issue_149", "GEIS", "THD I"], ["issue_149", "GEIS", "NSD I"], ["issue_149", "GEIS", "NSR I"], ["issue_149", "GEIS", "|I h2|"], ["issue_149", "GEIS", "|I h3|"], ["issue_149", "GEIS", "|I h4|"], ["issue_149", "GEIS", "|I h5|"], ["issue_149", "GEIS", "|I h6|"], ["issue_149", "GEIS", "|I h7|"], ["geis.mpr", "GEIS", "freq"], ["geis.mpr", "GEIS", "Re(Z)"], ["geis.mpr", "GEIS", "-Im(Z)"], ["geis.mpr", "GEIS", "|Z|"], ["geis.mpr", "GEIS", "Phase(Z)"], ["geis.mpr", "GEIS", "time"], ["geis.mpr", "GEIS", "Ewe"], ["geis.mpr", "GEIS", "I"], ["geis.mpr", "GEIS", "Cs"], ["geis.mpr", "GEIS", "Cp"], ["geis.mpr", "GEIS", "cycle number"], ["geis.mpr", "GEIS", "|Ewe|"], ["geis.mpr", "GEIS", "|I|"], ["geis.mpr", "GEIS", "(Q-Qo)"], ["geis.mpr", "GEIS", "Ece"], ["geis.mpr", "GEIS", "|Ece|"], ["geis.mpr", "GEIS", "Phase(Zce)"], ["geis.mpr", "GEIS", "|Zce|"], ["geis.mpr", "GEIS", "Re(Zce)"], ["geis.mpr", "GEIS", "-Im(Zce)"], ["geis.mpr", "GEIS", "Phase(Zwe-ce)"], ["geis.mpr", "GEIS", "|Zwe-ce|"], ["geis.mpr", "GEIS", "Re(Zwe-ce)"], ["geis.mpr", "GEIS", "-Im(Zwe-ce)"], ["lsv.issue_195.mpr", "LSV", "time"], ["lsv.issue_195.mpr", "LSV", "control"], ["lsv.issue_195.mpr", "LSV", "Ewe"], ["lsv.issue_195.mpr", "LSV", "I"], ["lsv.issue_195.mpr", "LSV", "(Q-Qo)"], ["lsv.issue_195.mpr", "LSV", "I Range"], ["lsv.issue_195.mpr", "LSV", "Ece"], ["lsv.issue_195.mpr", "LSV", "Analog IN 1"], ["lsv.issue_195.mpr", "LSV", "Analog IN 2"], ["lsv.issue_195.mpr", "LSV", "Pwe"], ["lsv.mpr", "LSV", "time"], ["lsv.mpr", "LSV", "control"], ["lsv.mpr", "LSV", "Ewe"], ["lsv.mpr", "LSV", "I"], ["lsv.mpr", "LSV", "(Q-Qo)"], ["lsv.mpr", "LSV", "Ece"], ["issue_149", "MB", "Ns"], ["issue_149", "MB", "I Range"], ["issue_149", "MB", "time"], ["issue_149", "MB", "control"], ["issue_149", "MB", "Ewe"], ["issue_149", "MB", "I"], ["issue_149", "MB", "dq"], ["issue_149", "MB", "(Q-Qo)"], ["issue_149", "MB", "|Energy|"], ["issue_149", "MB", "freq"], ["issue_149", "MB", "|Z|"], ["issue_149", "MB", "Phase(Z)"], ["issue_149", "MB", "Q charge or discharge"], ["issue_149", "MB", "Pwe"], ["issue_149", "MB", "THD Ewe"], ["issue_149", "MB", "NSD Ewe"], ["issue_149", "MB", "NSR Ewe"], ["issue_149", "MB", "|Ewe h2|"], ["issue_149", "MB", "|Ewe h3|"], ["issue_149", "MB", "|Ewe h4|"], ["issue_149", "MB", "|Ewe h5|"], ["issue_149", "MB", "|Ewe h6|"], ["issue_149", "MB", "|Ewe h7|"], ["issue_149", "MB", "THD I"], ["issue_149", "MB", "NSD I"], ["issue_149", "MB", "NSR I"], ["issue_149", "MB", "|I h2|"], ["issue_149", "MB", "|I h3|"], ["issue_149", "MB", "|I h4|"], ["issue_149", "MB", "|I h5|"], ["issue_149", "MB", "|I h6|"], ["issue_149", "MB", "|I h7|"], ["issue_149", "MB", "z cycle"], ["mb.issue_218.mpr", "MB", "Ns"], ["mb.issue_218.mpr", "MB", "I Range"], ["mb.issue_218.mpr", "MB", "time"], ["mb.issue_218.mpr", "MB", "control"], ["mb.issue_218.mpr", "MB", "Ewe"], ["mb.issue_218.mpr", "MB", "I"], ["mb.issue_218.mpr", "MB", "dq"], ["mb.issue_218.mpr", "MB", "(Q-Qo)"], ["mb.issue_218.mpr", "MB", "|Energy|"], ["mb.issue_218.mpr", "MB", "Q charge or discharge"], ["mb.issue_218.mpr", "MB", "Ece"], ["mb.issue_218.mpr", "MB", "Analog IN 1"], ["mb.issue_218.mpr", "MB", "Analog IN 2"], ["mb.issue_218.mpr", "MB", "Pwe"], ["mb.issue_223.mpr", "MB", "Ns"], ["mb.issue_223.mpr", "MB", "I Range"], ["mb.issue_223.mpr", "MB", "time"], ["mb.issue_223.mpr", "MB", "control"], ["mb.issue_223.mpr", "MB", "Ewe"], ["mb.issue_223.mpr", "MB", "I"], ["mb.issue_223.mpr", "MB", "dq"], ["mb.issue_223.mpr", "MB", "(Q-Qo)"], ["mb.issue_223.mpr", "MB", "freq"], ["mb.issue_223.mpr", "MB", "|Z|"], ["mb.issue_223.mpr", "MB", "Phase(Z)"], ["mb.issue_223.mpr", "MB", "Q charge or discharge"], ["mb.issue_223.mpr", "MB", "Energy we"], ["mb.issue_223.mpr", "MB", "z cycle"], ["mb.issue_95.mpr", "MB", "Ns"], ["mb.issue_95.mpr", "MB", "I Range"], ["mb.issue_95.mpr", "MB", "time"], ["mb.issue_95.mpr", "MB", "control"], ["mb.issue_95.mpr", "MB", "Ewe"], ["mb.issue_95.mpr", "MB", "I"], ["mb.issue_95.mpr", "MB", "dq"], ["mb.issue_95.mpr", "MB", "(Q-Qo)"], ["mb.issue_95.mpr", "MB", "|Energy|"], ["mb.issue_95.mpr", "MB", "Q charge or discharge"], ["mb.issue_95.mpr", "MB", "half cycle"], ["mb.issue_95.mpr", "MB", "Energy we charge"], ["mb.issue_95.mpr", "MB", "Energy we discharge"], ["mb.mpr", "MB", "Ns"], ["mb.mpr", "MB", "I Range"], ["mb.mpr", "MB", "time"], ["mb.mpr", "MB", "control"], ["mb.mpr", "MB", "Ewe"], ["mb.mpr", "MB", "I"], ["mb.mpr", "MB", "dq"], ["mb.mpr", "MB", "(Q-Qo)"], ["mb.mpr", "MB", "|Energy|"], ["mb.mpr", "MB", "freq"], ["mb.mpr", "MB", "|Z|"], ["mb.mpr", "MB", "Phase(Z)"], ["mb.mpr", "MB", "Q charge or discharge"], ["mb.mpr", "MB", "half cycle"], ["mb.mpr", "MB", "z cycle"], ["mb.mpr", "MB", "Energy we charge"], ["mb.mpr", "MB", "Energy we discharge"], ["mp.issue_183.mpr", "MP", "Ns"], ["mp.issue_183.mpr", "MP", "time"], ["mp.issue_183.mpr", "MP", "control"], ["mp.issue_183.mpr", "MP", "Ewe"], ["mp.issue_183.mpr", "MP", "I"], ["mp.issue_183.mpr", "MP", "dQ"], ["mp.issue_183.mpr", "MP", "I Range"], ["mp.issue_183.mpr", "MP", "Analog IN 1"], ["issue_149", "OCV", "time"], ["issue_149", "OCV", "Ewe"], ["ocv.mpr", "OCV", "time"], ["ocv.mpr", "OCV", "Ewe"], ["issue_149", "PEIS", "freq"], ["issue_149", "PEIS", "Re(Z)"], ["issue_149", "PEIS", "-Im(Z)"], ["issue_149", "PEIS", "|Z|"], ["issue_149", "PEIS", "Phase(Z)"], ["issue_149", "PEIS", "time"], ["issue_149", "PEIS", "Ewe"], ["issue_149", "PEIS", "I"], ["issue_149", "PEIS", "Cs"], ["issue_149", "PEIS", "Cp"], ["issue_149", "PEIS", "cycle number"], ["issue_149", "PEIS", "I Range"], ["issue_149", "PEIS", "|Ewe|"], ["issue_149", "PEIS", "|I|"], ["issue_149", "PEIS", "(Q-Qo)"], ["issue_149", "PEIS", "Pwe"], ["issue_149", "PEIS", "THD Ewe"], ["issue_149", "PEIS", "NSD Ewe"], ["issue_149", "PEIS", "NSR Ewe"], ["issue_149", "PEIS", "|Ewe h2|"], ["issue_149", "PEIS", "|Ewe h3|"], ["issue_149", "PEIS", "|Ewe h4|"], ["issue_149", "PEIS", "|Ewe h5|"], ["issue_149", "PEIS", "|Ewe h6|"], ["issue_149", "PEIS", "|Ewe h7|"], ["issue_149", "PEIS", "THD I"], ["issue_149", "PEIS", "NSD I"], ["issue_149", "PEIS", "NSR I"], ["issue_149", "PEIS", "|I h2|"], ["issue_149", "PEIS", "|I h3|"], ["issue_149", "PEIS", "|I h4|"], ["issue_149", "PEIS", "|I h5|"], ["issue_149", "PEIS", "|I h6|"], ["issue_149", "PEIS", "|I h7|"], ["issue_225", "PEIS", "freq"], ["issue_225", "PEIS", "Re(Z)"], ["issue_225", "PEIS", "-Im(Z)"], ["issue_225", "PEIS", "|Z|"], ["issue_225", "PEIS", "Phase(Z)"], ["issue_225", "PEIS", "time"], ["issue_225", "PEIS", "Ewe"], ["issue_225", "PEIS", "I"], ["issue_225", "PEIS", "Cs"], ["issue_225", "PEIS", "Cp"], ["issue_225", "PEIS", "I Range"], ["issue_225", "PEIS", "|Ewe|"], ["issue_225", "PEIS", "|I|"], ["issue_225", "PEIS", "(Q-Qo)"], ["issue_225", "PEIS", "Ece"], ["issue_225", "PEIS", "|Ece|"], ["issue_225", "PEIS", "Phase(Zce)"], ["issue_225", "PEIS", "|Zce|"], ["issue_225", "PEIS", "Re(Zce)"], ["issue_225", "PEIS", "-Im(Zce)"], ["issue_225", "PEIS", "Phase(Zwe-ce)"], ["issue_225", "PEIS", "|Zwe-ce|"], ["issue_225", "PEIS", "Re(Zwe-ce)"], ["issue_225", "PEIS", "-Im(Zwe-ce)"], ["issue_225", "PEIS", "freq"], ["issue_225", "PEIS", "Re(Z)"], ["issue_225", "PEIS", "-Im(Z)"], ["issue_225", "PEIS", "|Z|"], ["issue_225", "PEIS", "Phase(Z)"], ["issue_225", "PEIS", "time"], ["issue_225", "PEIS", "Ewe"], ["issue_225", "PEIS", "I"], ["issue_225", "PEIS", "Cs"], ["issue_225", "PEIS", "Cp"], ["issue_225", "PEIS", "I Range"], ["issue_225", "PEIS", "|Ewe|"], ["issue_225", "PEIS", "|I|"], ["issue_225", "PEIS", "(Q-Qo)"], ["issue_225", "PEIS", "freq"], ["issue_225", "PEIS", "Re(Z)"], ["issue_225", "PEIS", "-Im(Z)"], ["issue_225", "PEIS", "|Z|"], ["issue_225", "PEIS", "Phase(Z)"], ["issue_225", "PEIS", "time"], ["issue_225", "PEIS", "Ewe"], ["issue_225", "PEIS", "I"], ["issue_225", "PEIS", "Cs"], ["issue_225", "PEIS", "Cp"], ["issue_225", "PEIS", "I Range"], ["issue_225", "PEIS", "|Ewe|"], ["issue_225", "PEIS", "|I|"], ["issue_225", "PEIS", "(Q-Qo)"], ["issue_225", "PEIS", "Ece"], ["issue_225", "PEIS", "|Ece|"], ["issue_225", "PEIS", "Phase(Zce)"], ["issue_225", "PEIS", "|Zce|"], ["issue_225", "PEIS", "Re(Zce)"], ["issue_225", "PEIS", "-Im(Zce)"], ["issue_225", "PEIS", "Phase(Zwe-ce)"], ["issue_225", "PEIS", "|Zwe-ce|"], ["issue_225", "PEIS", "Re(Zwe-ce)"], ["issue_225", "PEIS", "-Im(Zwe-ce)"], ["peis.mpr", "PEIS", "freq"], ["peis.mpr", "PEIS", "Re(Z)"], ["peis.mpr", "PEIS", "-Im(Z)"], ["peis.mpr", "PEIS", "|Z|"], ["peis.mpr", "PEIS", "Phase(Z)"], ["peis.mpr", "PEIS", "time"], ["peis.mpr", "PEIS", "Ewe"], ["peis.mpr", "PEIS", "I"], ["peis.mpr", "PEIS", "Cs"], ["peis.mpr", "PEIS", "Cp"], ["peis.mpr", "PEIS", "|Ewe|"], ["peis.mpr", "PEIS", "|I|"], ["peis.mpr", "PEIS", "(Q-Qo)"], ["peis.mpr", "PEIS", "Ece"], ["peis.mpr", "PEIS", "|Ece|"], ["peis.mpr", "PEIS", "Phase(Zce)"], ["peis.mpr", "PEIS", "|Zce|"], ["peis.mpr", "PEIS", "Re(Zce)"], ["peis.mpr", "PEIS", "-Im(Zce)"], ["peis.mpr", "PEIS", "Phase(Zwe-ce)"], ["peis.mpr", "PEIS", "|Zwe-ce|"], ["peis.mpr", "PEIS", "Re(Zwe-ce)"], ["peis.mpr", "PEIS", "-Im(Zwe-ce)"], ["vsp_", "OCV", "time"], ["vsp_", "OCV", "Ewe"], ["vsp_", "OCV", "Analog IN 1"], ["vsp_", "OCV", "Analog IN 2"], ["vsp_", "OCV", "time"], ["vsp_", "OCV", "Ewe"], ["vsp_", "PEIS", "freq"], ["vsp_", "PEIS", "Re(Z)"], ["vsp_", "PEIS", "-Im(Z)"], ["vsp_", "PEIS", "|Z|"], ["vsp_", "PEIS", "Phase(Z)"], ["vsp_", "PEIS", "time"], ["vsp_", "PEIS", "Ewe"], ["vsp_", "PEIS", "I"], ["vsp_", "PEIS", "Cs"], ["vsp_", "PEIS", "Cp"], ["vsp_", "PEIS", "cycle number"], ["vsp_", "PEIS", "I Range"], ["vsp_", "PEIS", "|Ewe|"], ["vsp_", "PEIS", "|I|"], ["vsp_", "PEIS", "(Q-Qo)"], ["vsp_", "PEIS", "Analog IN 1"], ["vsp_", "PEIS", "Analog IN 2"]], "files": [["BCD", "bcd.issue_241.mpr", "bcd.issue_241.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "Q charge or discharge", "control", "dq", "half cycle", "time"]], [null, "bio_logic", "bio_logic2.mpr", ["Ewe", "Pwe", "control", "dq", "time"]], [null, "bio_logic", "bio_logic3.mpr", ["Ewe", "Ns", "Pwe", "control", "dq", "time"]], [null, "bio_logic", "bio_logic5.mpr", ["Ewe", "I", "Pwe", "control", "dQ", "time"]], [null, "bio_logic", "bio_logic6.mpr", ["(Q-Qo)", "Ewe", "I", "control", "cycle number", "time"]], ["CA", "ca.issue_134.mpr", "ca.issue_134.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Ewe", "I", "Ns", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["CA", "issue_149", "ca.issue_149.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["CA", "ca.mpr", "ca.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["coC", "issue_185", "coc.issue_185.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "dq", "half cycle", "step time", "time"]], ["coV", "issue_185", "cov.issue_185.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "dq", "half cycle", "step time", "time"]], ["CP", "issue_149", "cp.issue_149.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["CP", "cp.issue_61.mpr", "cp.issue_61.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["CP", "cp.mpr", "cp.mpr", ["(Q-Qo)", "Ece", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dQ", "half cycle", "time"]], ["CV", "issue_149", "cv.issue_149.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "Rcmp", "control", "cycle number", "step time", "time"]], ["CV", "cv.issue_217.mpr", "cv.issue_217.mpr", ["(Q-Qo)", "Ece", "Ewe", "I", "I Range", "Rcmp", "control", "cycle number", "time"]], ["CV", "cv.mpr", "cv.mpr", ["(Q-Qo)", "Ewe", "I", "control", "cycle number", "time"]], ["CVA", "cva.issue_135.mpr", "cva.issue_135.mpr", ["(Q-Qo)", "Ewe", "I", "control", "cycle number", "time"]], ["CVA", "cva.issue_202.mpr", "cva.issue_202.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "Ns", "Rcmp", "control", "cycle number", "time"]], ["GCPL", "issue_149", "gcpl.issue_149.mpr", ["(Q-Qo)", "Ewe", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "gcpl.issue_175.mpr", "gcpl.issue_175.mpr", ["(Q-Qo)", "Ewe", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "gcpl.issue_211.mpr", "gcpl.issue_211.mpr", ["(Q-Qo)", "Ece", "Energy we charge", "Energy we discharge", "Ewe", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "issue_226", "gcpl.issue_226.CxN.mpr", ["(Q-Qo)", "Ece", "Ewe", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "issue_226", "gcpl.issue_226.I.mpr", ["(Q-Qo)", "Ece", "Ewe", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "gcpl.issue_228.mpr", "gcpl.issue_228.mpr", ["(Q-Qo)", "Ewe", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "gcpl.issue_230.mpr", "gcpl.issue_230.mpr", ["(Q-Qo)", "Analog IN 1", "Capacitance charge", "Capacitance discharge", "Ece", "Energy ce charge", "Energy ce discharge", "Energy we charge", "Energy we discharge", "Ewe", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "step time", "time"]], ["GCPL", "gcpl.mpr", "gcpl.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "pr_182", "gcpl.pr_182.1.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Ece", "Energy we charge", "Energy we discharge", "Ewe", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GCPL", "pr_182", "gcpl.pr_182.2.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Ece", "Energy we charge", "Energy we discharge", "Ewe", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dq", "half cycle", "time"]], ["GEIS", "issue_149", "geis.issue_149.mpr", ["(Q-Qo)", "-Im(Z)", "Cp", "Cs", "Ewe", "I", "I Range", "NSD Ewe", "NSD I", "NSR Ewe", "NSR I", "Ns", "Phase(Z)", "Pwe", "Re(Z)", "THD Ewe", "THD I", "cycle number", "freq", "time", "|Ewe h2|", "|Ewe h3|", "|Ewe h4|", "|Ewe h5|", "|Ewe h6|", "|Ewe h7|", "|Ewe|", "|I h2|", "|I h3|", "|I h4|", "|I h5|", "|I h6|", "|I h7|", "|I|", "|Z|"]], ["GEIS", "geis.mpr", "geis.mpr", ["(Q-Qo)", "-Im(Z)", "-Im(Zce)", "-Im(Zwe-ce)", "Cp", "Cs", "Ece", "Ewe", "I", "I Range", "Phase(Z)", "Phase(Zce)", "Phase(Zwe-ce)", "Re(Z)", "Re(Zce)", "Re(Zwe-ce)", "cycle number", "freq", "time", "|Ece|", "|Ewe|", "|I|", "|Zce|", "|Zwe-ce|", "|Z|"]], ["LSV", "lsv.issue_195.mpr", "lsv.issue_195.mpr", ["(Q-Qo)", "Analog IN 1", "Analog IN 2", "Ece", "Ewe", "I", "I Range", "Pwe", "control", "time"]], ["LSV", "lsv.mpr", "lsv.mpr", ["(Q-Qo)", "Ece", "Ewe", "I", "I Range", "control", "time"]], ["MB", "issue_149", "mb.issue_149.mpr", ["(Q-Qo)", "Ewe", "I", "I Range", "NSD Ewe", "NSD I", "NSR Ewe", "NSR I", "Ns", "Phase(Z)", "Pwe", "Q charge or discharge", "THD Ewe", "THD I", "control", "dq", "freq", "half cycle", "time", "z cycle", "|Energy|", "|Ewe h2|", "|Ewe h3|", "|Ewe h4|", "|Ewe h5|", "|Ewe h6|", "|Ewe h7|", "|I h2|", "|I h3|", "|I h4|", "|I h5|", "|I h6|", "|I h7|", "|Z|"]], ["MB", "mb.issue_218.mpr", "mb.issue_218.mpr", ["(Q-Qo)", "Analog IN 1", "Analog IN 2", "Ece", "Ewe", "I", "I Range", "Ns", "Pwe", "Q charge or discharge", "control", "dq", "half cycle", "time", "|Energy|"]], ["MB", "mb.issue_223.mpr", "mb.issue_223.mpr", ["(Q-Qo)", "Energy we", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Q charge or discharge", "control", "dq", "freq", "half cycle", "time", "z cycle", "|Z|"]], ["MB", "mb.issue_95.mpr", "mb.issue_95.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Q charge or discharge", "control", "dq", "half cycle", "time", "|Energy|"]], ["MB", "mb.mpr", "mb.mpr", ["(Q-Qo)", "Capacitance charge", "Capacitance discharge", "Energy we charge", "Energy we discharge", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Q charge or discharge", "control", "dq", "freq", "half cycle", "time", "z cycle", "|Energy|", "|Z|"]], ["MP", "mp.issue_183.mpr", "mp.issue_183.mpr", ["Analog IN 1", "Ewe", "I", "I Range", "Ns", "control", "dQ", "time"]], ["OCV", "issue_149", "ocv.issue_149.mpr", ["Ewe", "time"]], ["OCV", "ocv.mpr", "ocv.mpr", ["Ewe", "time"]], ["OCV", "vsp_", "vsp_ocv_with.mpr", ["Analog IN 1", "Analog IN 2", "Ewe", "time"]], ["OCV", "vsp_", "vsp_ocv_wo.mpr", ["Ewe", "time"]], ["PEIS", "issue_149", "peis.issue_149.mpr", ["(Q-Qo)", "-Im(Z)", "Cp", "Cs", "Ewe", "I", "I Range", "NSD Ewe", "NSD I", "NSR Ewe", "NSR I", "Ns", "Phase(Z)", "Pwe", "Re(Z)", "THD Ewe", "THD I", "cycle number", "freq", "time", "|Ewe h2|", "|Ewe h3|", "|Ewe h4|", "|Ewe h5|", "|Ewe h6|", "|Ewe h7|", "|Ewe|", "|I h2|", "|I h3|", "|I h4|", "|I h5|", "|I h6|", "|I h7|", "|I|", "|Z|"]], ["PEIS", "issue_225", "peis.issue_225.ewe_ece.mpr", ["(Q-Qo)", "-Im(Z)", "-Im(Zce)", "-Im(Zwe-ce)", "Cp", "Cs", "Ece", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Phase(Zce)", "Phase(Zwe-ce)", "Re(Z)", "Re(Zce)", "Re(Zwe-ce)", "cycle number", "freq", "time", "|Ece|", "|Ewe|", "|I|", "|Zce|", "|Zwe-ce|", "|Z|"]], ["PEIS", "issue_225", "peis.issue_225.no_ece.mpr", ["(Q-Qo)", "-Im(Z)", "Cp", "Cs", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Re(Z)", "cycle number", "freq", "time", "|Ewe|", "|I|", "|Z|"]], ["PEIS", "issue_225", "peis.issue_225.with_ece.mpr", ["(Q-Qo)", "-Im(Z)", "-Im(Zce)", "-Im(Zwe-ce)", "Cp", "Cs", "Ece", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Phase(Zce)", "Phase(Zwe-ce)", "Re(Z)", "Re(Zce)", "Re(Zwe-ce)", "cycle number", "freq", "time", "|Ece|", "|Ewe|", "|I|", "|Zce|", "|Zwe-ce|", "|Z|"]], ["PEIS", "peis.mpr", "peis.mpr", ["(Q-Qo)", "-Im(Z)", "-Im(Zce)", "-Im(Zwe-ce)", "Cp", "Cs", "Ece", "Ewe", "I", "I Range", "Phase(Z)", "Phase(Zce)", "Phase(Zwe-ce)", "Re(Z)", "Re(Zce)", "Re(Zwe-ce)", "cycle number", "freq", "time", "|Ece|", "|Ewe|", "|I|", "|Zce|", "|Zwe-ce|", "|Z|"]], ["PEIS", "vsp_", "vsp_peis_with.mpr", ["(Q-Qo)", "-Im(Z)", "Analog IN 1", "Analog IN 2", "Cp", "Cs", "Ewe", "I", "I Range", "Ns", "Phase(Z)", "Re(Z)", "cycle number", "freq", "time", "|Ewe|", "|I|", "|Z|"]]]}
Binary file
rosetta_eclab/debug.py ADDED
@@ -0,0 +1,85 @@
1
+ """Show how the library scores pool columns of one name (development aid).
2
+
3
+ python -m namer.debug "Re(Z)" [--n 4]
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ import sys
10
+ import warnings
11
+
12
+ import numpy as np
13
+
14
+ from spike2 import corpus, features, tasks, vocab
15
+
16
+ from .engine import Context, Known, fit
17
+ from .evaluate import test_keys
18
+ from .library import LIBRARY
19
+
20
+
21
+ def main() -> int:
22
+ warnings.filterwarnings("ignore")
23
+ sys.stdout.reconfigure(encoding="utf-8")
24
+ ap = argparse.ArgumentParser()
25
+ ap.add_argument("name")
26
+ ap.add_argument("--n", type=int, default=4)
27
+ ap.add_argument("--fails", action="store_true", help="only show columns the pipeline gets wrong")
28
+ ap.add_argument("--probe", help="python expression over c (Context) to fit against the target, e.g. 'c.col(\"I\")'")
29
+ a = ap.parse_args()
30
+ excluded = test_keys()
31
+ shown = 0
32
+ for p in corpus.corpus_files():
33
+ try:
34
+ fd = tasks.file_data(p.name)
35
+ except Exception:
36
+ continue
37
+ if fd.n_points < tasks.MIN_ROWS:
38
+ continue
39
+ cols = tasks.usable_columns(fd)
40
+ for c in cols:
41
+ if vocab.canonical(c.name) != a.name or (p.name, c.position) in excluded or features.is_constant(c.values):
42
+ continue
43
+ others = [o for o in cols if o is not c]
44
+ if any(features.identical(c.values, o.values) for o in others):
45
+ continue # duplicates are not part of the pool
46
+ if a.fails:
47
+ from .evaluate import answer
48
+ ans = answer(c.values, c.dtype, others, fd.technique, vocab.names(), exclude_group=corpus.source_group(p.name))
49
+ if ans["verdict"] == "NAME" and ans["name"] == a.name:
50
+ continue
51
+ print(f"\n>> pipeline answer: {ans['verdict']} {ans.get('name')} | {ans.get('evidence', '')[:160]}")
52
+ known = {}
53
+ for o in others:
54
+ known.setdefault(vocab.canonical(o.name), Known(vocab.canonical(o.name), o.unit, np.asarray(o.values)))
55
+ ctx = Context(fd.technique, known, np.asarray(c.values), c.dtype)
56
+ y = np.asarray(c.values, dtype="f8")
57
+ print(f"\n== {p.name} ({fd.technique}) {c.name} [{c.unit}] {c.dtype}: min {y.min():.4g} max {y.max():.4g} "
58
+ f"distinct {np.unique(y).size} first {y[:6].round(5).tolist()}")
59
+ print(" known:", ", ".join(f"{k} [{v.unit}]" for k, v in known.items()))
60
+ ranking = []
61
+ for cand, spec in LIBRARY.items():
62
+ if cand in known:
63
+ continue
64
+ ev = spec.evaluate(ctx)
65
+ if ev:
66
+ ranking.append((ev.score, cand, ev.detail))
67
+ ranking.sort(reverse=True)
68
+ for s, cand, d in ranking[:5]:
69
+ print(f" {s:.3f} {cand}: {d}")
70
+ own = LIBRARY.get(a.name)
71
+ if own:
72
+ ev = own.evaluate(ctx)
73
+ print(f" OWN: {ev.score if ev else None} {ev.detail if ev else 'no relation testable'}")
74
+ if a.probe:
75
+ with np.errstate(all="ignore"):
76
+ f = fit(y, eval(a.probe, {"np": np, "c": ctx, **vars(sys.modules[f'{__package__}.library'])}))
77
+ print(f" PROBE {a.probe}: {f}")
78
+ shown += 1
79
+ if shown >= a.n:
80
+ return 0
81
+ return 0
82
+
83
+
84
+ if __name__ == "__main__":
85
+ raise SystemExit(main())
@@ -0,0 +1,203 @@
1
+ """Standalone column namer: no language model at run time.
2
+
3
+ For an unnamed column TARGET and the file's named columns, every candidate
4
+ quantity in the library (namer/library.py) is scored by code:
5
+
6
+ 1. relation checks: the candidate's defining relation to other columns (e.g.
7
+ dq = I*dt/3600) is computed from the known columns and fitted to TARGET;
8
+ the score uses r2 and whether the fitted scale matches the expected one
9
+ (unit conversions allowed), so dq, (Q-Qo) and Q charge/discharge separate.
10
+ 2. shape checks: properties that need no other column (monotonic clock,
11
+ integer counter stepping by 1, log-spaced frequency, small set of codes).
12
+ 3. abstention: if no candidate is supported well enough, the answer is
13
+ ABSTAIN with the best candidates listed as hints.
14
+
15
+ Every answer carries its evidence (the relation, r2, fitted scale), so a
16
+ maintainer can check it before adding the column to a parser.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass, field
22
+
23
+ import numpy as np
24
+
25
+
26
+ @dataclass
27
+ class Known:
28
+ name: str # canonical name (namer.library uses canonical names)
29
+ unit: str | None
30
+ values: np.ndarray
31
+ dtype: str = ""
32
+
33
+
34
+ @dataclass
35
+ class Context:
36
+ technique: str | None
37
+ known: dict[str, Known] # canonical name -> column
38
+ target: np.ndarray
39
+ target_dtype: str
40
+
41
+ def col(self, *names: str) -> np.ndarray | None:
42
+ for n in names:
43
+ if n in self.known:
44
+ return np.asarray(self.known[n].values, dtype="f8")
45
+ return None
46
+
47
+ def unit(self, *names: str) -> str | None:
48
+ for n in names:
49
+ if n in self.known:
50
+ return self.known[n].unit
51
+ return None
52
+
53
+
54
+ @dataclass
55
+ class Evidence:
56
+ candidate: str
57
+ score: float # 0..1
58
+ kind: str # "relation" | "shape" | "prior"
59
+ detail: str
60
+ extras: dict = field(default_factory=dict)
61
+
62
+
63
+ def fit(target: np.ndarray, pred: np.ndarray, robust: bool = True) -> tuple[float, float, float] | None:
64
+ """Least squares target ~ a*pred + b; returns (r2, a, b) or None if not testable."""
65
+ y = np.asarray(target, dtype="f8")
66
+ x = np.asarray(pred, dtype="f8")
67
+ m = np.isfinite(y) & np.isfinite(x)
68
+ if m.sum() < 3:
69
+ return None
70
+ y, x = y[m], x[m]
71
+ if np.ptp(y) == 0 or np.ptp(x) == 0:
72
+ return None
73
+ a, b = np.polyfit(x, y, 1)
74
+ res = y - (a * x + b)
75
+ ss = float(((y - y.mean()) ** 2).sum())
76
+ r2 = 1.0 - float((res ** 2).sum()) / ss
77
+ # Robust variant: real records have single glitch rows at step transitions. Refit without the worst
78
+ # 5% of rows (at least one, only for n >= 30 and a relation that already roughly holds).
79
+ n = y.size
80
+ if robust and n >= 30 and r2 < 0.999:
81
+ k = max(1, int(np.ceil(0.05 * n)))
82
+ a2, b2, r2t = a, b, r2
83
+ lev = np.argsort(np.abs(x - np.median(x)))[: n - k] # start without the k highest-leverage rows
84
+ if np.ptp(x[lev]) > 0:
85
+ a2, b2 = np.polyfit(x[lev], y[lev], 1)
86
+ for _ in range(3): # then trim by residual against the refitted line
87
+ keep = np.argsort(np.abs(y - (a2 * x + b2)))[: n - k]
88
+ yk, xk = y[keep], x[keep]
89
+ if np.ptp(yk) == 0 or np.ptp(xk) == 0:
90
+ break
91
+ a2, b2 = np.polyfit(xk, yk, 1)
92
+ ss2 = float(((yk - yk.mean()) ** 2).sum())
93
+ r2t = 1.0 - float(((yk - (a2 * xk + b2)) ** 2).sum()) / ss2
94
+ if r2t > r2:
95
+ return (r2t, float(a2), float(b2))
96
+ return (r2, float(a), float(b))
97
+
98
+
99
+ def scale_match(a: float, expected: list[float], tol: float = 0.03) -> float | None:
100
+ """Relative closeness of the fitted scale to any expected scale (None if no expectation)."""
101
+ if not expected:
102
+ return None
103
+ best = min(abs(a / e - 1.0) for e in expected if e)
104
+ return 1.0 if best <= tol else max(0.0, 1.0 - (best - tol) / 0.5)
105
+
106
+
107
+ CE_EIS = ("|Ece|", "|Zce|", "Re(Zce)", "-Im(Zce)", "Phase(Zce)", "|Zwe-ce|", "Re(Zwe-ce)", "-Im(Zwe-ce)",
108
+ "Phase(Zwe-ce)", "THD Ece", "NSD Ece", "NSR Ece")
109
+
110
+
111
+ def needs_ce_channel(name: str) -> bool:
112
+ return name in CE_EIS or name.startswith("|Ece h")
113
+
114
+
115
+ def has_ce_channel(present: set[str]) -> bool:
116
+ return any(n in present for n in ("Ece", "|Ece|", "|Zce|", "Re(Zce)", "-Im(Zce)", "Phase(Zce)"))
117
+
118
+
119
+ def single_sibling(ctx: Context, vocabulary: list[str], present: set[str], cooccur=None, library=None) -> Evidence | None:
120
+ """Exactly one candidate is one token away from exactly one known column of the same storage and magnitude
121
+ (e.g. Analog IN 2 next to a known Analog IN 1)."""
122
+ from spike2.elim import one_token_apart
123
+
124
+ y = np.asarray(ctx.target, dtype="f8")
125
+ y = y[np.isfinite(y)]
126
+ if y.size < 3:
127
+ return None
128
+ hits = []
129
+ for cand in vocabulary:
130
+ if cand in present:
131
+ continue
132
+ sibs = [k for k in present if one_token_apart(cand, k)]
133
+ if len(sibs) != 1:
134
+ continue
135
+ if ctx.known[sibs[0]].dtype != ctx.target_dtype:
136
+ continue
137
+ together = cooccur(cand, sibs[0]) if cooccur is not None else 0.0
138
+ if cooccur is not None and together < 0.5:
139
+ continue # not a pair that is normally recorded together
140
+ spec = library.get(cand) if library is not None else None
141
+ if spec is not None:
142
+ ev = spec.evaluate(ctx)
143
+ if ev is not None and ev.kind == "relation" and ev.extras.get("r2", 1.0) < 0.3:
144
+ continue # the candidate's own defining relation contradicts it
145
+ s = np.asarray(ctx.known[sibs[0]].values, dtype="f8")
146
+ s = s[np.isfinite(s)]
147
+ if s.size == 0:
148
+ continue
149
+ mag_t, mag_s = np.abs(y).max() + 1e-12, np.abs(s).max() + 1e-12
150
+ if 0.1 <= mag_t / mag_s <= 10 or together >= 0.9:
151
+ hits.append((cand, sibs[0]))
152
+ if len(hits) != 1:
153
+ return None
154
+ cand, sib = hits[0]
155
+ return Evidence(cand, 0.62, "sibling", f"the only missing sibling of the known column {sib}, with similar magnitude")
156
+
157
+
158
+ def name_column(ctx: Context, library, vocabulary: list[str], abstain_below: float = 0.6,
159
+ prior: dict[str, float] | None = None, cooccur=None) -> dict:
160
+ """Rank the vocabulary names that are not already present; return the answer with evidence."""
161
+ present = set(ctx.known)
162
+ evidences: list[Evidence] = []
163
+ for cand in vocabulary:
164
+ if cand in present:
165
+ continue
166
+ spec = library.get(cand)
167
+ if spec is None:
168
+ continue
169
+ ev = spec.evaluate(ctx)
170
+ if ev is not None:
171
+ if prior: # how common the name is for this technique breaks near-ties between equal relations
172
+ ev.score = ev.score + 0.03 * prior.get(cand, 0.0) # may exceed 1: only the order matters
173
+ evidences.append(ev)
174
+ sib = single_sibling(ctx, vocabulary, present, cooccur, library)
175
+ if sib is not None:
176
+ evidences.append(sib)
177
+ for e in evidences:
178
+ if e.kind != "relation" and needs_ce_channel(e.candidate) and not has_ce_channel(present):
179
+ e.score *= 0.2 # no other counter-electrode quantity was recorded in this file
180
+ evidences.sort(key=lambda e: -e.score)
181
+ def rival(e): # a relation with the wrong units is no rival
182
+ return e.kind != "relation" or e.extras.get("scale_match", 1.0) >= 0.5
183
+
184
+ rivals = [e for e in evidences[1:] if rival(e)] if evidences else []
185
+ if (evidences and evidences[0].score < abstain_below and evidences[0].kind == "relation"
186
+ and evidences[0].score >= 0.3 and evidences[0].extras.get("r2", 0) >= 0.8
187
+ and evidences[0].extras.get("scale_match", 0) >= 0.5
188
+ and (not rivals or rivals[0].score <= 0.25 * evidences[0].score)):
189
+ top = evidences[0]
190
+ return {"verdict": "NAME", "name": top.candidate, "confidence": round(0.5 * top.score, 3),
191
+ "alternatives": [e.candidate for e in evidences[1:3]],
192
+ "evidence": f"approximate relation, far ahead of every alternative: {top.detail}",
193
+ "ranking": [(e.candidate, round(e.score, 3), e.detail[:90]) for e in evidences[:5]]}
194
+ if not evidences or evidences[0].score < abstain_below:
195
+ return {"verdict": "ABSTAIN", "name": "NONE", "confidence": evidences[0].score if evidences else 0.0,
196
+ "alternatives": [e.candidate for e in evidences[:2]],
197
+ "ranking": [(e.candidate, round(e.score, 3), e.detail[:90]) for e in evidences[:5]],
198
+ "evidence": "; ".join(f"{e.candidate}: {e.detail}" for e in evidences[:3]) or "no candidate fits"}
199
+ top = evidences[0]
200
+ margin = top.score - (evidences[1].score if len(evidences) > 1 else 0.0)
201
+ return {"verdict": "NAME", "name": top.candidate, "confidence": round(min(1.0, min(1.0, top.score) * (0.5 + margin)), 3),
202
+ "alternatives": [e.candidate for e in evidences[1:3]],
203
+ "evidence": f"{top.kind}: {top.detail}", "ranking": [(e.candidate, round(e.score, 3), e.detail[:90]) for e in evidences[:5]]}