better-rtplot 0.4.14__tar.gz → 0.4.15__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.
Files changed (36) hide show
  1. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/PKG-INFO +6 -1
  2. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/README.md +5 -0
  3. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/pyproject.toml +1 -1
  4. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/server_browser.py +25 -10
  5. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/index.html +13 -13
  6. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/LICENSE +0 -0
  7. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/client.py +0 -0
  8. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/interactive_test.py +0 -0
  9. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/saved_plots/.gitignore +0 -0
  10. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/server.py +0 -0
  11. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/server_browser_gui.py +0 -0
  12. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/auto-render.min.js +0 -0
  13. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  14. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  15. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  16. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  17. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  18. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  19. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  20. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  21. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  22. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  23. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  24. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  25. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  26. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  27. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  28. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  29. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  30. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  31. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  32. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  33. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/katex.min.css +0 -0
  34. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/katex/katex.min.js +0 -0
  35. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/uPlot.iife.min.js +0 -0
  36. {better_rtplot-0.4.14 → better_rtplot-0.4.15}/rtplot/static/uPlot.min.css +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: better-rtplot
3
- Version: 0.4.14
3
+ Version: 0.4.15
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: jmontp
@@ -67,6 +67,11 @@ Sender and server don't have to be on the same machine — see the
67
67
  No Python needed on the viewing machine. On Windows the binary opens
68
68
  a small Tk status window showing the listening URL.
69
69
 
70
+ To arrange several plots side by side, start the server with
71
+ `./rtplot-server --columns 2` (or `--columns 3`). The Python server accepts
72
+ the same option: `python -m rtplot.server_browser --columns 2`. See the
73
+ [multi-column example](examples/05_multi_column/).
74
+
70
75
  **Client** — pip install in the env that runs your script:
71
76
 
72
77
  ```bash
@@ -43,6 +43,11 @@ Sender and server don't have to be on the same machine — see the
43
43
  No Python needed on the viewing machine. On Windows the binary opens
44
44
  a small Tk status window showing the listening URL.
45
45
 
46
+ To arrange several plots side by side, start the server with
47
+ `./rtplot-server --columns 2` (or `--columns 3`). The Python server accepts
48
+ the same option: `python -m rtplot.server_browser --columns 2`. See the
49
+ [multi-column example](examples/05_multi_column/).
50
+
46
51
  **Client** — pip install in the env that runs your script:
47
52
 
48
53
  ```bash
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "better-rtplot"
3
- version = "0.4.14"
3
+ version = "0.4.15"
4
4
  description = ""
5
5
  authors = ["jmontp <jmontp@umich.edu>"]
6
6
  license = "MIT"
@@ -98,8 +98,17 @@ parser.add_argument(
98
98
  parser.add_argument(
99
99
  "-c",
100
100
  "--column",
101
- help="Create new plots in separate columns instead of rows",
102
- action="store_false",
101
+ dest="columns",
102
+ help="Shortcut for --columns 2",
103
+ action="store_const",
104
+ const=2,
105
+ )
106
+
107
+ parser.add_argument(
108
+ "--columns",
109
+ type=int,
110
+ metavar="N",
111
+ help="Arrange plots in N columns (default: 1)",
103
112
  )
104
113
 
105
114
  parser.add_argument(
@@ -180,7 +189,9 @@ parser.add_argument(
180
189
 
181
190
  args = parser.parse_args()
182
191
 
183
- NEW_SUBPLOT_IN_ROW = args.column
192
+ PLOT_COLUMNS = args.columns if args.columns is not None else 1
193
+ if PLOT_COLUMNS < 1:
194
+ parser.error("--columns must be at least 1")
184
195
  DEBUG_TEXT_ENABLED = args.debug
185
196
  SKIP_PLOT_DATAPOINTS = args.skip
186
197
  ADAPT_SKIP_PLOT_DATAPOINTS = args.adaptable
@@ -607,7 +618,8 @@ def build_config_message(tab: Tab, config_dict) -> dict:
607
618
  "slider_values": dict(tab.slider_values),
608
619
  "text_values": dict(tab.text_values),
609
620
  "display_values": dict(tab.display_values),
610
- "row_layout": bool(NEW_SUBPLOT_IN_ROW),
621
+ "columns": PLOT_COLUMNS,
622
+ "row_layout": PLOT_COLUMNS == 1,
611
623
  }
612
624
 
613
625
 
@@ -1517,9 +1529,9 @@ _SNAPSHOT_TEMPLATE = """<!doctype html>
1517
1529
  <style>
1518
1530
  html, body { margin: 0; padding: 0; background: #fafafa; color: #222;
1519
1531
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
1520
- #plots { display: flex; flex-direction: column; gap: 12px;
1521
- max-width: 900px; margin: 0 auto; padding: 20px 16px; }
1522
- .plot-wrap { background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px; }
1532
+ #plots { display: grid; grid-template-columns: repeat(var(--plot-columns, 1), minmax(320px, 1fr));
1533
+ gap: 12px; overflow-x: auto; max-width: 900px; margin: 0 auto; padding: 20px 16px; }
1534
+ .plot-wrap { background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px; min-width: 0; }
1523
1535
  .snap-footer { text-align: center; font-size: 12px; color: #999; padding: 8px 0 20px; }
1524
1536
  .snap-footer a { color: #2a5db0; text-decoration: none; }
1525
1537
  .snap-footer a:hover { text-decoration: underline; }
@@ -1539,6 +1551,8 @@ _SNAPSHOT_TEMPLATE = """<!doctype html>
1539
1551
  (function () {
1540
1552
  const SNAP = __SNAPSHOT_JSON__;
1541
1553
  const plotsDiv = document.getElementById('plots');
1554
+ plotsDiv.style.setProperty('--plot-columns', SNAP.columns || 1);
1555
+ plotsDiv.style.maxWidth = `${900 * (SNAP.columns || 1)}px`;
1542
1556
  const COLOR_MAP = { r:'rgb(255,0,0)', g:'rgb(0,200,0)', b:'rgb(0,0,255)',
1543
1557
  c:'rgb(0,200,200)', m:'rgb(200,0,200)',
1544
1558
  y:'rgb(200,200,0)', k:'rgb(0,0,0)' };
@@ -1578,7 +1592,7 @@ _SNAPSHOT_TEMPLATE = """<!doctype html>
1578
1592
  data.push(Float64Array.from(src));
1579
1593
  }
1580
1594
  const opts = {
1581
- width: Math.max(640, plotsDiv.clientWidth - 40),
1595
+ width: Math.max(240, wrap.clientWidth - 16),
1582
1596
  height: 260,
1583
1597
  title: pcfg.title || '',
1584
1598
  scales: {
@@ -1591,7 +1605,7 @@ _SNAPSHOT_TEMPLATE = """<!doctype html>
1591
1605
  cursor: { drag: { x: true, y: false } },
1592
1606
  };
1593
1607
  const u = new uPlot(opts, data, wrap);
1594
- plots.push({ uplot: u, data: data, xs: xs, xrange: xrange,
1608
+ plots.push({ uplot: u, wrap: wrap, data: data, xs: xs, xrange: xrange,
1595
1609
  traceCount: traceCount, startIdx: traceOffset });
1596
1610
  traceOffset += traceCount;
1597
1611
  });
@@ -1625,7 +1639,7 @@ _SNAPSHOT_TEMPLATE = """<!doctype html>
1625
1639
  window.addEventListener('resize', function () {
1626
1640
  plots.forEach(function (p) {
1627
1641
  p.uplot.setSize({
1628
- width: Math.max(640, plotsDiv.clientWidth - 40),
1642
+ width: Math.max(240, p.wrap.clientWidth - 16),
1629
1643
  height: 260,
1630
1644
  });
1631
1645
  });
@@ -1707,6 +1721,7 @@ def _build_snapshot_html(tab: Tab, animate: bool) -> str:
1707
1721
 
1708
1722
  payload = {
1709
1723
  "plots": plots,
1724
+ "columns": PLOT_COLUMNS,
1710
1725
  "num_samples": int(hi - lo),
1711
1726
  "trace_data": trace_data,
1712
1727
  "animate": bool(animate),
@@ -62,10 +62,9 @@
62
62
  #ws-status { font-size: calc(12px * var(--ui-scale)); color: #666; margin-left: auto; }
63
63
 
64
64
  /* -------- Plots + controls (existing) -------- */
65
- #plots { display: flex; padding: 12px; gap: 12px; }
66
- #plots.row { flex-direction: column; }
67
- #plots.col { flex-direction: row; flex-wrap: wrap; }
68
- .plot-wrap { background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px; flex: 1 1 auto; min-width: 320px; }
65
+ #plots { display: grid; grid-template-columns: repeat(var(--plot-columns, 1), minmax(320px, 1fr)); padding: 12px; gap: 12px; overflow-x: auto; }
66
+ .plot-wrap { background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px; min-width: 0; }
67
+ #plots .ctrl-row, #plots #empty-state { grid-column: 1 / -1; }
69
68
  .plot-title { font-size: 13px; font-weight: 600; margin: 0 0 4px 4px; color: #333; }
70
69
  #empty-state { padding: 28px 32px; color: #888; font-size: calc(14px * var(--ui-scale)); font-style: italic; }
71
70
  /* Persistent banner the server raises when a client-supplied plot
@@ -853,8 +852,12 @@
853
852
  const plotHeight = (Number.isFinite(heightMul) && heightMul > 0)
854
853
  ? Math.round(baseHeight * heightMul)
855
854
  : baseHeight;
855
+ const wrap = document.createElement('div');
856
+ wrap.className = 'plot-wrap';
857
+ plotsDiv.appendChild(wrap);
858
+
856
859
  const opts = {
857
- width: Math.max(640, plotsDiv.clientWidth - 40),
860
+ width: Math.max(240, wrap.clientWidth - 16),
858
861
  height: plotHeight,
859
862
  title: pcfg.title || '',
860
863
  scales: {
@@ -870,10 +873,6 @@
870
873
  cursor: { drag: { x: false, y: false } },
871
874
  };
872
875
 
873
- const wrap = document.createElement('div');
874
- wrap.className = 'plot-wrap';
875
- plotsDiv.appendChild(wrap);
876
-
877
876
  const buffers = [];
878
877
  for (let t = 0; t < traceCount; t++) {
879
878
  const buf = new Float32Array(xrange);
@@ -887,6 +886,7 @@
887
886
  const u = new uPlot(opts, initialData, wrap);
888
887
  plots.push({
889
888
  uplot: u,
889
+ wrap: wrap,
890
890
  xs: xs,
891
891
  traceCount: traceCount,
892
892
  startIdx: traceOffset,
@@ -899,8 +899,8 @@
899
899
 
900
900
  function buildPlots(cfg) {
901
901
  destroyPlots();
902
- plotsDiv.classList.toggle('row', cfg.row_layout);
903
- plotsDiv.classList.toggle('col', !cfg.row_layout);
902
+ const columns = Number(cfg.columns) || (cfg.row_layout === false ? 2 : 1);
903
+ plotsDiv.style.setProperty('--plot-columns', Math.max(1, Math.floor(columns)));
904
904
 
905
905
  const controls = cfg.controls || [];
906
906
  const layout = (cfg.layout && cfg.layout.length)
@@ -913,7 +913,7 @@
913
913
  if (entry.kind === 'plot') {
914
914
  const pcfg = cfg.plots[entry.index];
915
915
  if (!pcfg) return;
916
- traceOffset += buildOnePlot(pcfg, cfg.row_layout, traceOffset);
916
+ traceOffset += buildOnePlot(pcfg, columns === 1, traceOffset);
917
917
  } else if (entry.kind === 'controls') {
918
918
  const row = controls[entry.index];
919
919
  if (!row) return;
@@ -1366,7 +1366,7 @@
1366
1366
  window.addEventListener('resize', () => {
1367
1367
  plots.forEach(p => {
1368
1368
  p.uplot.setSize({
1369
- width: Math.max(640, plotsDiv.clientWidth - 40),
1369
+ width: Math.max(240, p.wrap.clientWidth - 16),
1370
1370
  height: p.height,
1371
1371
  });
1372
1372
  });
File without changes