fullplot 0.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.
- fullplot/__init__.py +61 -0
- fullplot/cli.py +63 -0
- fullplot/fullplot.py +1647 -0
- fullplot/hdf5.py +48 -0
- fullplot/maps.py +708 -0
- fullplot/themes.py +176 -0
- fullplot-0.0.1.dist-info/METADATA +119 -0
- fullplot-0.0.1.dist-info/RECORD +10 -0
- fullplot-0.0.1.dist-info/WHEEL +4 -0
- fullplot-0.0.1.dist-info/entry_points.txt +3 -0
fullplot/themes.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
DARK_COLORS = [
|
|
5
|
+
"#00ff00", # green
|
|
6
|
+
"#ff0000", # red
|
|
7
|
+
"#ffff00", # yellow
|
|
8
|
+
"#00ffff", # cyan
|
|
9
|
+
"#ff00ff", # magenta
|
|
10
|
+
"#ff9900", # orange
|
|
11
|
+
"#ffffff", # white
|
|
12
|
+
"#3399ff", # blue
|
|
13
|
+
"#ff66cc", # pink
|
|
14
|
+
"#99ff00", # lime
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
LIGHT_COLORS = [
|
|
18
|
+
"#b00000", # dark red
|
|
19
|
+
"#0047ab", # stronger blue
|
|
20
|
+
"#007a33", # darker green
|
|
21
|
+
"#a020a0", # purple / magenta
|
|
22
|
+
"#c46a00", # burnt orange
|
|
23
|
+
"#007a7a", # teal
|
|
24
|
+
"#5a3dbb", # violet-blue
|
|
25
|
+
"#000000", # black
|
|
26
|
+
"#8a6a00", # olive-gold
|
|
27
|
+
"#444444", # dark gray
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def check_theme(theme: str) -> str:
|
|
32
|
+
theme = str(theme).lower().strip()
|
|
33
|
+
|
|
34
|
+
if theme not in ("dark", "light"):
|
|
35
|
+
raise ValueError("theme must be either 'dark' or 'light'.")
|
|
36
|
+
|
|
37
|
+
return theme
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def theme_colors(theme: str):
|
|
41
|
+
theme = check_theme(theme)
|
|
42
|
+
|
|
43
|
+
if theme == "dark":
|
|
44
|
+
return DARK_COLORS
|
|
45
|
+
|
|
46
|
+
return LIGHT_COLORS
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def theme_settings(theme: str):
|
|
50
|
+
theme = check_theme(theme)
|
|
51
|
+
|
|
52
|
+
if theme == "dark":
|
|
53
|
+
return {
|
|
54
|
+
"figure_facecolor": "#000000",
|
|
55
|
+
"axes_facecolor": "#000000",
|
|
56
|
+
"text_color": "#ffffff",
|
|
57
|
+
"spine_color": "#ffffff",
|
|
58
|
+
"grid_color": "#8a8a8a",
|
|
59
|
+
"legend_facecolor": "#000000",
|
|
60
|
+
"legend_edgecolor": "#ffffff",
|
|
61
|
+
"axis_color": "#ffffff",
|
|
62
|
+
"line_width": 1.7,
|
|
63
|
+
"spine_width": 1.0,
|
|
64
|
+
"grid_linestyle": "--",
|
|
65
|
+
"grid_linewidth": 0.7,
|
|
66
|
+
"grid_alpha": 0.85,
|
|
67
|
+
"font_family": "monospace",
|
|
68
|
+
"label_weight": "bold",
|
|
69
|
+
"map_cmap": "plasma",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
"figure_facecolor": "#f7f7f2",
|
|
74
|
+
"axes_facecolor": "#f7f7f2",
|
|
75
|
+
"text_color": "#000000",
|
|
76
|
+
"spine_color": "#000000",
|
|
77
|
+
"grid_color": "#000000",
|
|
78
|
+
"legend_facecolor": "#f7f7f2",
|
|
79
|
+
"legend_edgecolor": "#000000",
|
|
80
|
+
"axis_color": "#000000",
|
|
81
|
+
"line_width": 1.7,
|
|
82
|
+
"spine_width": 1.0,
|
|
83
|
+
"grid_linestyle": "--",
|
|
84
|
+
"grid_linewidth": 0.7,
|
|
85
|
+
"grid_alpha": 0.60,
|
|
86
|
+
"font_family": "monospace",
|
|
87
|
+
"label_weight": "bold",
|
|
88
|
+
"map_cmap": "viridis",
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def apply_theme(fig, axes, theme: str):
|
|
93
|
+
settings = theme_settings(theme)
|
|
94
|
+
colors = theme_colors(theme)
|
|
95
|
+
|
|
96
|
+
if not isinstance(axes, (list, tuple)):
|
|
97
|
+
axes = [axes]
|
|
98
|
+
|
|
99
|
+
fig.patch.set_facecolor(settings["figure_facecolor"])
|
|
100
|
+
|
|
101
|
+
for ax in axes:
|
|
102
|
+
if ax is None:
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
ax.set_facecolor(settings["axes_facecolor"])
|
|
106
|
+
ax.set_prop_cycle(color=colors)
|
|
107
|
+
|
|
108
|
+
ax.tick_params(
|
|
109
|
+
axis="both",
|
|
110
|
+
colors=settings["axis_color"],
|
|
111
|
+
direction="in",
|
|
112
|
+
length=5,
|
|
113
|
+
width=1.0,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
ax.xaxis.label.set_color(settings["axis_color"])
|
|
117
|
+
ax.yaxis.label.set_color(settings["axis_color"])
|
|
118
|
+
ax.title.set_color(settings["text_color"])
|
|
119
|
+
|
|
120
|
+
ax.xaxis.label.set_fontfamily(settings["font_family"])
|
|
121
|
+
ax.yaxis.label.set_fontfamily(settings["font_family"])
|
|
122
|
+
ax.title.set_fontfamily(settings["font_family"])
|
|
123
|
+
|
|
124
|
+
ax.xaxis.label.set_fontweight(settings["label_weight"])
|
|
125
|
+
ax.yaxis.label.set_fontweight(settings["label_weight"])
|
|
126
|
+
ax.title.set_fontweight(settings["label_weight"])
|
|
127
|
+
|
|
128
|
+
for spine in ax.spines.values():
|
|
129
|
+
spine.set_color(settings["spine_color"])
|
|
130
|
+
spine.set_linewidth(settings["spine_width"])
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def grid_kwargs(theme: str):
|
|
134
|
+
settings = theme_settings(theme)
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
"color": settings["grid_color"],
|
|
138
|
+
"linestyle": settings["grid_linestyle"],
|
|
139
|
+
"linewidth": settings["grid_linewidth"],
|
|
140
|
+
"alpha": settings["grid_alpha"],
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def style_legend(legend, theme: str):
|
|
145
|
+
if legend is None:
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
settings = theme_settings(theme)
|
|
149
|
+
|
|
150
|
+
frame = legend.get_frame()
|
|
151
|
+
frame.set_facecolor(settings["legend_facecolor"])
|
|
152
|
+
frame.set_edgecolor(settings["legend_edgecolor"])
|
|
153
|
+
frame.set_alpha(1.0)
|
|
154
|
+
|
|
155
|
+
for text in legend.get_texts():
|
|
156
|
+
text.set_color(settings["text_color"])
|
|
157
|
+
text.set_fontfamily(settings["font_family"])
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def style_colorbar(colorbar, theme: str):
|
|
161
|
+
settings = theme_settings(theme)
|
|
162
|
+
|
|
163
|
+
colorbar.ax.yaxis.label.set_color(settings["text_color"])
|
|
164
|
+
colorbar.ax.yaxis.label.set_fontfamily(settings["font_family"])
|
|
165
|
+
colorbar.ax.yaxis.label.set_fontweight(settings["label_weight"])
|
|
166
|
+
|
|
167
|
+
colorbar.ax.tick_params(
|
|
168
|
+
colors=settings["axis_color"],
|
|
169
|
+
direction="in",
|
|
170
|
+
length=5,
|
|
171
|
+
width=1.0,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
for spine in colorbar.ax.spines.values():
|
|
175
|
+
spine.set_color(settings["spine_color"])
|
|
176
|
+
spine.set_linewidth(settings["spine_width"])
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fullplot
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A lightweight HDF5 trace plotting, filtering, and map-generation helper for engineering data.
|
|
5
|
+
Keywords: hdf5,plotting,engineering,simulation,test-data,map-generation,scientific-computing
|
|
6
|
+
Author: Saaketh Ramoju
|
|
7
|
+
Author-email: Saaketh Ramoju <skramoju@gmail.com>
|
|
8
|
+
License-Expression: GPL-3.0-only
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Intended Audience :: Education
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
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
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
19
|
+
Requires-Dist: numpy>=1.26.0
|
|
20
|
+
Requires-Dist: scipy>=1.11.0
|
|
21
|
+
Requires-Dist: h5py>=3.10.0
|
|
22
|
+
Requires-Dist: matplotlib>=3.8.0
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Project-URL: Homepage, https://github.com/saakethramoju/FullPlot
|
|
25
|
+
Project-URL: Repository, https://github.com/saakethramoju/FullPlot
|
|
26
|
+
Project-URL: Issues, https://github.com/saakethramoju/FullPlot/issues
|
|
27
|
+
Project-URL: PyPI, https://pypi.org/project/fullplot/
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# FullPlot
|
|
31
|
+
|
|
32
|
+
FullPlot is a lightweight HDF5 plotting, trace filtering, and map-generation package for engineering simulation and test data.
|
|
33
|
+
|
|
34
|
+
FullPlot is intentionally independent from FullFlow. FullPlot does not import FullFlow, and FullFlow does not import FullPlot. HDF5 files are the interface between the two packages.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install fullplot
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For local development with `uv`:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv sync --dev
|
|
46
|
+
uv run pytest
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Quick plotting
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import fullplot as fplt
|
|
53
|
+
|
|
54
|
+
run = fplt.open("engine_sim.h5")
|
|
55
|
+
run.tree()
|
|
56
|
+
run.list()
|
|
57
|
+
|
|
58
|
+
run.plot(
|
|
59
|
+
x="time",
|
|
60
|
+
y="node_pressure",
|
|
61
|
+
xlabel="Time [s]",
|
|
62
|
+
ylabel="Pressure [Pa]",
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Traces
|
|
67
|
+
|
|
68
|
+
A `Trace` is a generic one-dimensional line of data. It can represent simulation data, test data, a filtered trace, a redline, a blueline, a command trace, or a derived trace.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import fullplot as fplt
|
|
72
|
+
|
|
73
|
+
run = fplt.open("hotfire.h5")
|
|
74
|
+
|
|
75
|
+
chpt = run.trace("CHPT", x="time")
|
|
76
|
+
chpt_filtered = chpt.filter("moving_average", window=0.05)
|
|
77
|
+
redline = fplt.Trace.constant("CHPT Redline", x=chpt.x, y=400.0, role="redline")
|
|
78
|
+
|
|
79
|
+
fplt.plot([chpt, chpt_filtered, redline])
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Generated traces
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import numpy as np
|
|
86
|
+
import fullplot as fplt
|
|
87
|
+
|
|
88
|
+
time = np.linspace(0.0, 10.0, 1001)
|
|
89
|
+
|
|
90
|
+
command = fplt.Trace.from_points(
|
|
91
|
+
"Main Ox Valve Command",
|
|
92
|
+
points=[(0.0, 0.0), (1.0, 0.0), (1.1, 1.0), (8.0, 1.0), (8.1, 0.0)],
|
|
93
|
+
x=time,
|
|
94
|
+
mode="previous",
|
|
95
|
+
role="command",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
fplt.plot(command)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Map generation
|
|
102
|
+
|
|
103
|
+
FullPlot can generate rectangular HDF5 maps that another package, including FullFlow, can consume later.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import fullplot as fplt
|
|
107
|
+
|
|
108
|
+
fplt.generate_map(
|
|
109
|
+
"demo_map.h5",
|
|
110
|
+
group="properties",
|
|
111
|
+
axes=[
|
|
112
|
+
fplt.Axis.linear("pressure", 1.0e5, 5.0e5, 5),
|
|
113
|
+
fplt.Axis.linear("temperature", 250.0, 500.0, 6),
|
|
114
|
+
],
|
|
115
|
+
evaluate=lambda pressure, temperature: {
|
|
116
|
+
"density": pressure / (287.0 * temperature),
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
fullplot/__init__.py,sha256=rZ_u84Ch70gReH4G3fZr2iVn0mjGs7LVkh4cFMu-g-Q,1060
|
|
2
|
+
fullplot/cli.py,sha256=XXoBT8kDIp7l3TG7ZQ5dYmHzNY4u-lc-5KsEu4o38d0,1455
|
|
3
|
+
fullplot/fullplot.py,sha256=Cp1K6N2T0HflyJAODvq22CI5XhkaE_D2nixMWWOdkDM,50206
|
|
4
|
+
fullplot/hdf5.py,sha256=NGb_sHHz2X5QuspiJlmyMBbZn135kUNiR1qWRkbCw-o,1345
|
|
5
|
+
fullplot/maps.py,sha256=9n-Q_y05VVljxFjx1ucMIeSSpHxsFQm7G_ETsT5YO3M,24156
|
|
6
|
+
fullplot/themes.py,sha256=CqiJLvYQ4M5ZRl-NmHr7lYrAsnrqWSsL3hK9xtcy200,4723
|
|
7
|
+
fullplot-0.0.1.dist-info/WHEEL,sha256=uOqnPWqgFlbov4NeTCercq7cBQ2UN7xh5fiW55lOnAg,81
|
|
8
|
+
fullplot-0.0.1.dist-info/entry_points.txt,sha256=4jALe-r2n_VzCxE1P4AsajIpUdkPq56IZWWOlZqPrq8,48
|
|
9
|
+
fullplot-0.0.1.dist-info/METADATA,sha256=VVsLBQPQL6o5RB5Mvzkse5gnaE587Uw7S9QeQhNpIkE,3216
|
|
10
|
+
fullplot-0.0.1.dist-info/RECORD,,
|