jarvisplot 1.0.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.
Files changed (42) hide show
  1. jarvisplot/Figure/adapters.py +773 -0
  2. jarvisplot/Figure/cards/std_axes_adapter_config.json +23 -0
  3. jarvisplot/Figure/data_pipelines.py +87 -0
  4. jarvisplot/Figure/figure.py +1573 -0
  5. jarvisplot/Figure/helper.py +217 -0
  6. jarvisplot/Figure/load_data.py +252 -0
  7. jarvisplot/__init__.py +0 -0
  8. jarvisplot/cards/a4paper/1x1/ternary.json +6 -0
  9. jarvisplot/cards/a4paper/2x1/rect.json +106 -0
  10. jarvisplot/cards/a4paper/2x1/rect5x1.json +344 -0
  11. jarvisplot/cards/a4paper/2x1/rect_cmap.json +181 -0
  12. jarvisplot/cards/a4paper/2x1/ternary.json +139 -0
  13. jarvisplot/cards/a4paper/2x1/ternary_cmap.json +189 -0
  14. jarvisplot/cards/a4paper/4x1/rect.json +106 -0
  15. jarvisplot/cards/a4paper/4x1/rect_cmap.json +174 -0
  16. jarvisplot/cards/a4paper/4x1/ternary.json +139 -0
  17. jarvisplot/cards/a4paper/4x1/ternary_cmap.json +189 -0
  18. jarvisplot/cards/args.json +50 -0
  19. jarvisplot/cards/colors/colormaps.json +140 -0
  20. jarvisplot/cards/default/output.json +11 -0
  21. jarvisplot/cards/gambit/1x1/ternary.json +6 -0
  22. jarvisplot/cards/gambit/2x1/rect_cmap.json +200 -0
  23. jarvisplot/cards/gambit/2x1/ternary.json +139 -0
  24. jarvisplot/cards/gambit/2x1/ternary_cmap.json +205 -0
  25. jarvisplot/cards/icons/JarvisHEP.png +0 -0
  26. jarvisplot/cards/icons/gambit.png +0 -0
  27. jarvisplot/cards/icons/gambit_small.png +0 -0
  28. jarvisplot/cards/style_preference.json +23 -0
  29. jarvisplot/cli.py +64 -0
  30. jarvisplot/client.py +6 -0
  31. jarvisplot/config.py +69 -0
  32. jarvisplot/core.py +237 -0
  33. jarvisplot/data_loader.py +441 -0
  34. jarvisplot/inner_func.py +162 -0
  35. jarvisplot/utils/__init__.py +0 -0
  36. jarvisplot/utils/cmaps.py +258 -0
  37. jarvisplot/utils/interpolator.py +377 -0
  38. jarvisplot-1.0.1.dist-info/METADATA +80 -0
  39. jarvisplot-1.0.1.dist-info/RECORD +42 -0
  40. jarvisplot-1.0.1.dist-info/WHEEL +5 -0
  41. jarvisplot-1.0.1.dist-info/entry_points.txt +2 -0
  42. jarvisplot-1.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,377 @@
1
+ # src/utils/interpolator.py
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from typing import Any, Callable, Dict, Optional, Tuple, Literal
7
+
8
+
9
+ BoundsMode = Literal["clamp", "extrapolate", "nan", "error"]
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class CSVSourceSpec:
14
+ """Where to read x/y pairs from."""
15
+ path: str # relative to YAML dir or absolute
16
+ x: str # column name (or index key later)
17
+ y: str # column name
18
+ sort_by: Optional[str] = None
19
+ drop_duplicates: Optional[str] = None
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class Interp1DSpec:
24
+ """Interpolation method + options."""
25
+ kind: str = "linear"
26
+ bounds: BoundsMode = "clamp"
27
+ fill_value: Optional[float] = None
28
+ assume_sorted: bool = False
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class InterpolatorSpec:
33
+ """Single named interpolator spec parsed from YAML."""
34
+ name: str
35
+ source: CSVSourceSpec
36
+ method: str = "interp1d" # keep extensible: "interp1d", "pchip", ...
37
+ options: Interp1DSpec = Interp1DSpec()
38
+
39
+
40
+ class LazyCallable:
41
+ """
42
+ A callable wrapper that builds the real function on first call.
43
+
44
+ IMPORTANT: This is what you inject into eval globals so Figure/layer code
45
+ doesn't need to know about lazy loading.
46
+ """
47
+ def __init__(self, name: str, builder: Callable[[], Callable], logger=None):
48
+ self._name = name
49
+ self._builder = builder
50
+ self._logger = logger
51
+ self._fn: Optional[Callable] = None
52
+
53
+ def _ensure(self) -> Callable:
54
+ if self._fn is None:
55
+ if self._logger:
56
+ self._logger.debug(f"LazyLoad: building interpolator '{self._name}'")
57
+ self._fn = self._builder()
58
+ return self._fn
59
+
60
+ def __call__(self, *args, **kwargs):
61
+ fn = self._ensure()
62
+ return fn(*args, **kwargs)
63
+
64
+
65
+ class InterpolatorManager:
66
+ """
67
+ Parses YAML 'Functions' and provides lazy-callable interpolators.
68
+
69
+ - Parsing stage: stores specs only (no IO, no scipy work)
70
+ - Runtime stage: first call triggers CSV read + interpolator build
71
+ - Cache: built callables are cached for reuse in the same run
72
+
73
+ Suggested usage:
74
+ mgr = InterpolatorManager.from_yaml(cfg, yaml_dir, shared, logger)
75
+ funcs_dict = mgr.as_eval_funcs() # inject into expression globals
76
+ # expression can call f_cut(x) directly
77
+ """
78
+
79
+ def __init__(self, yaml_dir: Path, shared=None, logger=None):
80
+ self._yaml_dir = Path(yaml_dir)
81
+ self._shared = shared
82
+ self._logger = logger
83
+
84
+ self._specs: Dict[str, InterpolatorSpec] = {}
85
+ self._lazy: Dict[str, LazyCallable] = {}
86
+ self._built: Dict[str, Callable] = {}
87
+
88
+ # -------------------------
89
+ # YAML parsing (no IO)
90
+ # -------------------------
91
+ @classmethod
92
+ def from_yaml(
93
+ cls,
94
+ config: Any,
95
+ yaml_dir: str | Path,
96
+ shared=None,
97
+ logger=None,
98
+ key: str = "Functions",
99
+ ) -> "InterpolatorManager":
100
+ """
101
+ Parse config[key] list into specs and register lazy wrappers.
102
+
103
+ Accepts either the full YAML config dict (with top-level key 'Functions'), or
104
+ directly a list (cfg['Functions']).
105
+ """
106
+ mgr = cls(yaml_dir=Path(yaml_dir), shared=shared, logger=logger)
107
+
108
+ # Accept either the full YAML config dict (preferred) or directly a list (cfg['Functions']).
109
+ if isinstance(config, list):
110
+ items = config
111
+ elif isinstance(config, dict):
112
+ items = config.get(key, []) or []
113
+ else:
114
+ items = []
115
+
116
+ for item in items:
117
+ spec = mgr._parse_one(item)
118
+ mgr.register(spec)
119
+ return mgr
120
+
121
+ def _parse_one(self, item: Dict[str, Any]) -> InterpolatorSpec:
122
+ """
123
+ Convert a single YAML dict -> InterpolatorSpec.
124
+
125
+ Expected YAML shape (example):
126
+ - name: f_cut
127
+ source: {type: csv, path: ./a.csv, x: x, y: y, sort_by: x, drop_duplicates: x}
128
+ method: interp1d
129
+ options: {kind: linear, bounds: clamp, fill_value: null, assume_sorted: false}
130
+
131
+ Top-level YAML key is 'Functions'.
132
+ """
133
+ # NOTE: only parse + validate keys here; do NOT read files.
134
+ if not isinstance(item, dict):
135
+ raise TypeError(f"Function spec must be a dict, got {type(item)}")
136
+
137
+ name = item.get("name", None)
138
+ if not name:
139
+ raise ValueError("Function spec missing required field 'name'")
140
+
141
+ source = item.get("source", None)
142
+ if not isinstance(source, dict):
143
+ raise ValueError(f"Function '{name}': missing/invalid 'source'")
144
+
145
+ stype = source.get("type", None)
146
+ if stype != "csv":
147
+ raise ValueError(f"Function '{name}': only source.type='csv' is supported (got {stype!r})")
148
+
149
+ path = source.get("path", None)
150
+ xcol = source.get("x", None)
151
+ ycol = source.get("y", None)
152
+ if not path or xcol is None or ycol is None:
153
+ raise ValueError(f"Function '{name}': source requires 'path', 'x', 'y'")
154
+
155
+ src = CSVSourceSpec(
156
+ path=str(path),
157
+ x=str(xcol),
158
+ y=str(ycol),
159
+ sort_by=source.get("sort_by", None),
160
+ drop_duplicates=source.get("drop_duplicates", None),
161
+ )
162
+
163
+ method = item.get("method", "interp1d")
164
+ if method != "interp1d":
165
+ raise ValueError(f"Function '{name}': only method='interp1d' is supported (got {method!r})")
166
+
167
+ opt0 = item.get("options", {}) or {}
168
+ if not isinstance(opt0, dict):
169
+ raise ValueError(f"Function '{name}': options must be a dict")
170
+
171
+ opt = Interp1DSpec(
172
+ kind=str(opt0.get("kind", "linear")),
173
+ bounds=str(opt0.get("bounds", "clamp")),
174
+ fill_value=opt0.get("fill_value", None),
175
+ assume_sorted=bool(opt0.get("assume_sorted", False)),
176
+ )
177
+
178
+ if opt.kind != "linear":
179
+ raise ValueError(f"Function '{name}': only options.kind='linear' is supported (got {opt.kind!r})")
180
+
181
+ return InterpolatorSpec(name=name, source=src, method=method, options=opt)
182
+
183
+ # -------------------------
184
+ # Registry
185
+ # -------------------------
186
+ def register(self, spec: InterpolatorSpec) -> None:
187
+ """
188
+ Register a spec and create a LazyCallable wrapper for it.
189
+ """
190
+ name = spec.name
191
+ if name in self._specs:
192
+ raise ValueError(f"Interpolator '{name}' already registered.")
193
+ self._specs[name] = spec
194
+
195
+ # wrap a builder closure; builder will do IO + build actual callable
196
+ self._lazy[name] = LazyCallable(name, builder=lambda n=name: self._build(n), logger=self._logger)
197
+
198
+ def get(self, name: str) -> Callable:
199
+ """
200
+ Return callable for this interpolator. (LazyCallable until built.)
201
+ """
202
+ if name in self._built:
203
+ return self._built[name]
204
+ if name in self._lazy:
205
+ return self._lazy[name]
206
+ raise KeyError(f"Unknown interpolator '{name}'")
207
+
208
+ def as_eval_funcs(self) -> Dict[str, Callable]:
209
+ """
210
+ Dict suitable for injection into expression evaluation globals.
211
+ Keys are interpolator names; values are LazyCallable instances.
212
+ """
213
+ return dict(self._lazy)
214
+
215
+ def summary(self) -> Dict[str, Any]:
216
+ """
217
+ Small diagnostic summary: registered / built status.
218
+ """
219
+ return {
220
+ "registered": sorted(self._specs.keys()),
221
+ "built": sorted(self._built.keys()),
222
+ }
223
+
224
+ # -------------------------
225
+ # Lazy build (IO + compute)
226
+ # -------------------------
227
+ def _build(self, name: str) -> Callable:
228
+ """
229
+ Build the real interpolator callable for `name`, cache it, and return it.
230
+
231
+ Responsibilities:
232
+ - read (x, y) from CSV (may use shared cache)
233
+ - construct interpolator according to method/options
234
+ - return a vectorized callable f(x) -> y
235
+ """
236
+ if name in self._built:
237
+ return self._built[name]
238
+ if name not in self._specs:
239
+ raise KeyError(f"Unknown interpolator '{name}'")
240
+
241
+ spec = self._specs[name]
242
+
243
+ # Load data
244
+ x, y = self._load_csv_xy(spec.source)
245
+
246
+ # Build callable
247
+ if spec.method != "interp1d":
248
+ raise ValueError(f"Function '{name}': unsupported method {spec.method!r}")
249
+
250
+ fn = self._make_interp1d(x, y, spec.options)
251
+ self._built[name] = fn
252
+ return fn
253
+
254
+ # -------------------------
255
+ # Helpers (placeholders)
256
+ # -------------------------
257
+ def _resolve_path(self, p: str) -> Path:
258
+ """
259
+ Resolve YAML-relative path or absolute path.
260
+ """
261
+ p = str(p)
262
+ if p.startswith("&JP/"):
263
+ # allow internal JP paths if needed; resolve relative to project root (yaml_dir's parent)
264
+ # but keep simple: treat as relative to yaml_dir for now.
265
+ p = p[4:]
266
+ path = Path(p).expanduser()
267
+ if not path.is_absolute():
268
+ path = (self._yaml_dir / path).resolve()
269
+ return path
270
+
271
+ def _load_csv_xy(self, spec: CSVSourceSpec) -> Tuple[Any, Any]:
272
+ """
273
+ Read/clean CSV and return arrays (x, y).
274
+ """
275
+ import pandas as _pd
276
+ import numpy as _np
277
+
278
+ csv_path = self._resolve_path(spec.path)
279
+ df = _pd.read_csv(csv_path)
280
+
281
+ # Optional sort/dedup on a specified column name
282
+ if spec.sort_by is not None and spec.sort_by in df.columns:
283
+ df = df.sort_values(by=spec.sort_by)
284
+
285
+ if spec.drop_duplicates is not None and spec.drop_duplicates in df.columns:
286
+ df = df.drop_duplicates(subset=spec.drop_duplicates, keep="first")
287
+
288
+ # Allow spec.x/spec.y to be either column names OR python expressions.
289
+ import math as _math
290
+ from ..inner_func import update_funcs as _update_funcs
291
+
292
+ local_vars = df.to_dict("series")
293
+ allowed_globals = _update_funcs({"np": _np, "math": _math})
294
+
295
+ def _eval_field(field: str):
296
+ if field in df.columns:
297
+ return _np.asarray(df[field].values, dtype=float)
298
+ # treat as expression
299
+ try:
300
+ arr = eval(field, allowed_globals, local_vars)
301
+ return _np.asarray(arr, dtype=float)
302
+ except Exception as e:
303
+ raise ValueError(
304
+ f"CSV {csv_path}: cannot evaluate field '{field}'. "
305
+ f"Not a column and eval failed: {e}"
306
+ )
307
+
308
+ x = _eval_field(spec.x)
309
+ y = _eval_field(spec.y)
310
+
311
+ if x.shape != y.shape:
312
+ raise ValueError(f"CSV {csv_path}: evaluated x/y have different shapes: {x.shape} vs {y.shape}")
313
+
314
+ # Ensure x is sorted for interpolation unless explicitly assumed sorted.
315
+ # Even if user sorted by another column, we still need monotonic x.
316
+ order = _np.argsort(x)
317
+ x = x[order]
318
+ y = y[order]
319
+
320
+ return x, y
321
+
322
+ def _make_interp1d(self, x, y, opt: Interp1DSpec) -> Callable:
323
+ """
324
+ Create interp1d-like callable based on opt.
325
+ """
326
+ import numpy as _np
327
+
328
+ x = _np.asarray(x, dtype=float)
329
+ y = _np.asarray(y, dtype=float)
330
+
331
+ if x.ndim != 1 or y.ndim != 1 or x.shape[0] < 2 or x.shape != y.shape:
332
+ raise ValueError("interp1d: x and y must be 1D arrays of the same length >= 2")
333
+
334
+ xmin = float(_np.min(x))
335
+ xmax = float(_np.max(x))
336
+
337
+ def _linear_extrap(xq: _np.ndarray) -> _np.ndarray:
338
+ # linear extrapolation using the first/last segments
339
+ yq = _np.interp(xq, x, y)
340
+ left = xq < xmin
341
+ right = xq > xmax
342
+ if left.any():
343
+ x0, x1 = x[0], x[1]
344
+ y0, y1 = y[0], y[1]
345
+ slope = (y1 - y0) / (x1 - x0)
346
+ yq[left] = y0 + slope * (xq[left] - x0)
347
+ if right.any():
348
+ x0, x1 = x[-2], x[-1]
349
+ y0, y1 = y[-2], y[-1]
350
+ slope = (y1 - y0) / (x1 - x0)
351
+ yq[right] = y1 + slope * (xq[right] - x1)
352
+ return yq
353
+
354
+ def f(xq):
355
+ xq = _np.asarray(xq, dtype=float)
356
+ if opt.bounds == "clamp":
357
+ xqc = _np.clip(xq, xmin, xmax)
358
+ return _np.interp(xqc, x, y)
359
+ elif opt.bounds == "extrapolate":
360
+ return _linear_extrap(xq)
361
+ elif opt.bounds == "nan":
362
+ yq = _np.interp(_np.clip(xq, xmin, xmax), x, y)
363
+ out = (xq < xmin) | (xq > xmax)
364
+ if out.any():
365
+ yq = yq.astype(float, copy=False)
366
+ yq[out] = _np.nan
367
+ return yq
368
+ elif opt.bounds == "error":
369
+ if _np.any((xq < xmin) | (xq > xmax)):
370
+ raise ValueError("interp1d: query x is out of bounds")
371
+ return _np.interp(xq, x, y)
372
+ else:
373
+ # fallback
374
+ xqc = _np.clip(xq, xmin, xmax)
375
+ return _np.interp(xqc, x, y)
376
+
377
+ return f
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: jarvisplot
3
+ Version: 1.0.1
4
+ Summary: JarvisPLOT: YAML-driven plotting engine
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: loguru
8
+ Requires-Dist: pyyaml
9
+ Requires-Dist: jsonschema
10
+ Requires-Dist: numpy
11
+ Requires-Dist: pandas
12
+ Requires-Dist: matplotlib
13
+
14
+ # JarvisPLOT
15
+
16
+ JarvisPLOT is a lightweight, Python/Matplotlib-based plotting framework developed for **Jarvis-HEP**,
17
+ but it can also be used as a **standalone scientific plotting tool**.
18
+
19
+ It provides a simple command-line interface (CLI) to generate publication-quality figures from YAML configuration files, with most layout and style decisions handled by predefined profiles and style cards.
20
+
21
+ ---
22
+
23
+ ## Command-Line Usage
24
+
25
+ Display help information:
26
+
27
+ ```bash
28
+ jplot -h
29
+ ```
30
+
31
+ Run JarvisPLOT with one or more YAML configuration files:
32
+
33
+ ```bash
34
+ jplot path/to/config.yaml
35
+ ```
36
+
37
+ ### Example: SUSYRun2 Ternary Plots
38
+
39
+ ```bash
40
+ jplot ./bin/SUSYRun2_EWMSSM.yaml
41
+ jplot ./bin/SUSYRun2_GEWMSSM.yaml
42
+ ```
43
+
44
+ > **Note:** The data file paths inside the YAML files must be updated to match your local setup.
45
+
46
+ ---
47
+
48
+ ## Notes
49
+
50
+ - Figures are saved automatically to the output paths defined in the YAML configuration.
51
+ - Common output formats include PNG and PDF (backend-dependent).
52
+ - JarvisPLOT works in headless environments (SSH, batch jobs) without any GUI backend.
53
+
54
+ ---
55
+
56
+ ## Requirements
57
+
58
+ ### Python
59
+ - **Python ≥ 3.9** (tested on 3.9–3.12)
60
+
61
+ ### Required Packages
62
+ - `numpy`
63
+ - `pandas`
64
+ - `matplotlib`
65
+ - `pyyaml`
66
+ - `jsonschema`
67
+ - `scipy` — numerical utilities
68
+ - `h5py` — required for loading HDF5 data files
69
+
70
+ ### Github Page
71
+ [https://github.com/Pengxuan-Zhu-Phys/Jarvis-PLOT](https://github.com/Pengxuan-Zhu-Phys/Jarvis-PLOT)
72
+
73
+ ### Documentation
74
+ [https://pengxuan-zhu-phys.github.io/Jarvis-Docs/](https://pengxuan-zhu-phys.github.io/Jarvis-Docs/)
75
+
76
+ ---
77
+
78
+ ## License
79
+
80
+ MIT License
@@ -0,0 +1,42 @@
1
+ jarvisplot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ jarvisplot/cli.py,sha256=QwVmR48yHPsGbGSWqNj8Pbo53nYaLSPrhMa3LPvsiNI,2543
3
+ jarvisplot/client.py,sha256=vjcxT4Y9v8F0nfqId4ROSE0xbbZW7cv-rIxOwh2LzFk,115
4
+ jarvisplot/config.py,sha256=edHNoumh4bDjzj7hP1dGM6chCz_El4qNPA_wL4M3LCQ,2282
5
+ jarvisplot/core.py,sha256=7ekrBL9UejjUYYTub8zYh2aOvSiEyp7V4T8vjhuCHhM,8890
6
+ jarvisplot/data_loader.py,sha256=QIN3NZPSl63xGSH_3C2upmj1-aTfkZrLY-oK6g8Lrz4,16740
7
+ jarvisplot/inner_func.py,sha256=hQeoJzVeTVjIb8_qRbHPf0_5lj-y0QEdOZEy-Yowm88,4158
8
+ jarvisplot/Figure/adapters.py,sha256=END12kkzmhnG_bJddfQ3CQy0P3DlrY5I6WRl2DfiKlU,28502
9
+ jarvisplot/Figure/data_pipelines.py,sha256=4mOHyYEHkqUCsEvDL2X7l2hE9ya2HyE0rmVqJLJ6b9E,3348
10
+ jarvisplot/Figure/figure.py,sha256=yPfKXiN-ahXuiR4x-xVAhzyRBoXdC41yofDAWF0S6a4,66593
11
+ jarvisplot/Figure/helper.py,sha256=5CJtJrKhIn7h-uBe7QWL9s2BoMIU9-JLtLmSSs86F80,7424
12
+ jarvisplot/Figure/load_data.py,sha256=U7dgJuHJJsLAonuFc0fMLbmWCJO5qnJsi4p6e3WrnSU,8997
13
+ jarvisplot/Figure/cards/std_axes_adapter_config.json,sha256=lokkIg-QIBZQ-lJr28cRbFdlvGP9-cCd64UIF9mnpxg,478
14
+ jarvisplot/cards/args.json,sha256=Rh4Qmd-Otsg4-IymPoMA5NqXLaPpajvNNezrdtliX_E,1439
15
+ jarvisplot/cards/style_preference.json,sha256=WbkrIa4RwEaHuMmyP_QO3nkjaU8M6COAMjexOCr-AX8,901
16
+ jarvisplot/cards/a4paper/1x1/ternary.json,sha256=kPz74R976P2HEl4e5yETFhukJIGHpekuH8LtkurXp94,69
17
+ jarvisplot/cards/a4paper/2x1/rect.json,sha256=zZ4Yo7i0_b4qNZp30AFVnLsWMPk9jPBIYdaJQDoT1Pc,2767
18
+ jarvisplot/cards/a4paper/2x1/rect5x1.json,sha256=uB4TcwxOIE2xnCeHLxCk_mS0M_ZMEP8pBuK_O6NX0a0,10318
19
+ jarvisplot/cards/a4paper/2x1/rect_cmap.json,sha256=ZiWxYMbqJvwulfDLR4-njwzcZf_I3DfK7hhfePT-MIw,5125
20
+ jarvisplot/cards/a4paper/2x1/ternary.json,sha256=hJl9B7o0Bg8Wl0InRo5PNyDc3FpPfdPmk7DmvQQNu6w,4051
21
+ jarvisplot/cards/a4paper/2x1/ternary_cmap.json,sha256=Av6MuK9z3S2Vpfvmb0QyxS1b7y0bjsIUvc6elB1J3As,5335
22
+ jarvisplot/cards/a4paper/4x1/rect.json,sha256=zZ4Yo7i0_b4qNZp30AFVnLsWMPk9jPBIYdaJQDoT1Pc,2767
23
+ jarvisplot/cards/a4paper/4x1/rect_cmap.json,sha256=TuoT_D-D2HcsQGiab-3NFlP-XJUtP9qv0kPcyUiT7wI,4842
24
+ jarvisplot/cards/a4paper/4x1/ternary.json,sha256=hJl9B7o0Bg8Wl0InRo5PNyDc3FpPfdPmk7DmvQQNu6w,4051
25
+ jarvisplot/cards/a4paper/4x1/ternary_cmap.json,sha256=Av6MuK9z3S2Vpfvmb0QyxS1b7y0bjsIUvc6elB1J3As,5335
26
+ jarvisplot/cards/colors/colormaps.json,sha256=mTiR9OmYjpYaby0F4jwddTbYNzfL86QkHECannTbYzQ,3839
27
+ jarvisplot/cards/default/output.json,sha256=x562t9OPPG4p8fubUPJz2CEyw2GxQYVIEUMMQB_Klpg,135
28
+ jarvisplot/cards/gambit/1x1/ternary.json,sha256=kPz74R976P2HEl4e5yETFhukJIGHpekuH8LtkurXp94,69
29
+ jarvisplot/cards/gambit/2x1/rect_cmap.json,sha256=SrxBn3Z8vLWi4tnZvv8eXFYwzQKzZZ7V1Ea3DRjDsfI,5595
30
+ jarvisplot/cards/gambit/2x1/ternary.json,sha256=hJl9B7o0Bg8Wl0InRo5PNyDc3FpPfdPmk7DmvQQNu6w,4051
31
+ jarvisplot/cards/gambit/2x1/ternary_cmap.json,sha256=sBTeGq7DVUutRNalbzQqIlUQZXmzxC0Xobc3_Btdmhg,5871
32
+ jarvisplot/cards/icons/JarvisHEP.png,sha256=iDXEeQhA6T7REjIoae6XEj619_z7IlWqhnY9JaLPAww,399549
33
+ jarvisplot/cards/icons/gambit.png,sha256=z6BRjaVbnAMhtWzCEf53VCfEFPxoMbEYWsOT9ZNyfOE,246969
34
+ jarvisplot/cards/icons/gambit_small.png,sha256=maQSLO4PPSn4_J9rqIqp0qvY4Rtpx9GiiPl7ONrieKk,83453
35
+ jarvisplot/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ jarvisplot/utils/cmaps.py,sha256=2IKOUzsOZb8KReEggbNCNAdzS6IhWrcMMSUw03CunpM,9449
37
+ jarvisplot/utils/interpolator.py,sha256=CG6Wi6BX2cAI-TdL0d51J9wXnjxawc4R_uPlNoXHfss,13126
38
+ jarvisplot-1.0.1.dist-info/METADATA,sha256=wk9MzJuePhkdxrnd_bNLzAPNjYgsmF5uUOjGh0rjH34,1864
39
+ jarvisplot-1.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
40
+ jarvisplot-1.0.1.dist-info/entry_points.txt,sha256=1dvnP7V3PTjdtL3G8OIDEKopJlDFJccC0EzFKmvp4jM,49
41
+ jarvisplot-1.0.1.dist-info/top_level.txt,sha256=Rvy30upSt2sE_reLghmQejiBTIo5t6HXLnMwIsiKWS8,11
42
+ jarvisplot-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ jplot = jarvisplot.client:main
@@ -0,0 +1 @@
1
+ jarvisplot