onsaemiro 1.0.0__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.
- onsaemiro-1.0.0/LICENSE +21 -0
- onsaemiro-1.0.0/PKG-INFO +249 -0
- onsaemiro-1.0.0/README.md +223 -0
- onsaemiro-1.0.0/pyproject.toml +48 -0
- onsaemiro-1.0.0/setup.cfg +4 -0
- onsaemiro-1.0.0/src/onsaemiro/__init__.py +880 -0
- onsaemiro-1.0.0/src/onsaemiro.egg-info/PKG-INFO +249 -0
- onsaemiro-1.0.0/src/onsaemiro.egg-info/SOURCES.txt +9 -0
- onsaemiro-1.0.0/src/onsaemiro.egg-info/dependency_links.txt +1 -0
- onsaemiro-1.0.0/src/onsaemiro.egg-info/requires.txt +4 -0
- onsaemiro-1.0.0/src/onsaemiro.egg-info/top_level.txt +1 -0
onsaemiro-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hanseul Kang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
onsaemiro-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: onsaemiro
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Publication-quality scientific visualisation and reporting utilities
|
|
5
|
+
Author-email: Hanseul Kang <hanseul.kang@aalto.fi>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/PentagonToy/Onsaemiro
|
|
8
|
+
Project-URL: Issues, https://github.com/PentagonToy/Onsaemiro/issues
|
|
9
|
+
Keywords: matplotlib,scientific-visualisation,publication,plotting,jupyter
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy
|
|
22
|
+
Requires-Dist: matplotlib
|
|
23
|
+
Requires-Dist: rich
|
|
24
|
+
Requires-Dist: ipython
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# Onsaemiro
|
|
28
|
+
|
|
29
|
+
**Publication-quality matplotlib styling for Academic Research.**
|
|
30
|
+
|
|
31
|
+
Onsaemiro provides a streamlined interface for generating figures that meet the rigorous standards of scientific journals. It handles font scaling, consistent subplot positioning, colour-blind friendly palettes, and GitHub-safe progress bars — all with minimal boilerplate.
|
|
32
|
+
|
|
33
|
+
***
|
|
34
|
+
|
|
35
|
+
## Key Features
|
|
36
|
+
|
|
37
|
+
* **Fixed-Fraction Layout**: Prevents axes jumping between figures by enforcing consistent subplot dimensions.
|
|
38
|
+
* **Automatic Scaling**: Adjusts font sizes, line widths, and tick marks based on the physical figure width.
|
|
39
|
+
* **Academic Palettes**: Built-in support for Okabe-Ito, Paul Tol (Vibrant, Muted, Bright), and IBM palettes.
|
|
40
|
+
* **TableMaker**: Renders LaTeX-style "booktabs" tables directly in Jupyter notebooks or the terminal.
|
|
41
|
+
* **ProgressBar / `track()`**: Static-HTML progress bar that survives GitHub's notebook renderer — no ipywidgets required.
|
|
42
|
+
* **Context Management**: Use `fixed_frame` for one-off figures with specific dimensions without affecting global settings.
|
|
43
|
+
|
|
44
|
+
***
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
Install Onsaemiro from PyPI:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install onsaemiro
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The package is published on PyPI and can also be installed directly from a local clone.
|
|
55
|
+
|
|
56
|
+
For local development, clone the repository, move into the package directory, and run:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install -e .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The `-e` (editable) flag means changes to the Onsaemiro source are reflected immediately — no reinstall needed.
|
|
63
|
+
|
|
64
|
+
***
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import onsaemiro as osm
|
|
70
|
+
import matplotlib.pyplot as plt
|
|
71
|
+
import numpy as np
|
|
72
|
+
|
|
73
|
+
# 1. Global setup
|
|
74
|
+
osm.set_style(figure_size=(3.5, 2.5), palette="okabe-ito")
|
|
75
|
+
|
|
76
|
+
# 2. Get the palette
|
|
77
|
+
colors = osm.get_palette()
|
|
78
|
+
|
|
79
|
+
# 3. Plotting
|
|
80
|
+
x = np.linspace(0, 10, 100)
|
|
81
|
+
fig, ax = plt.subplots()
|
|
82
|
+
|
|
83
|
+
ax.plot(x, np.sin(x), color=colors['blue'], label='Signal A')
|
|
84
|
+
ax.plot(x, np.cos(x), color=colors['orange'], label='Signal B')
|
|
85
|
+
|
|
86
|
+
ax.set_xlabel('Time (s)')
|
|
87
|
+
ax.set_ylabel('Amplitude (V)')
|
|
88
|
+
ax.legend()
|
|
89
|
+
|
|
90
|
+
# 4. Finalise (handles legend borders and origin overlaps)
|
|
91
|
+
osm.finalize(ax)
|
|
92
|
+
plt.show()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
***
|
|
96
|
+
|
|
97
|
+
## Core Components
|
|
98
|
+
|
|
99
|
+
### 1. Global Styling (`set_style`)
|
|
100
|
+
|
|
101
|
+
Configures `plt.rcParams` for publication. Unlike standard matplotlib behaviour, it disables `autolayout` to ensure that labels do not shift the axes box. Defaults to a Times-style serif font.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
osm.set_style(
|
|
105
|
+
base_fontsize=12.5,
|
|
106
|
+
linewidth=1.2,
|
|
107
|
+
figure_size=(3.5, 2.5),
|
|
108
|
+
use_tex=False
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 2. Colour Palettes (`Palette`)
|
|
113
|
+
|
|
114
|
+
Access colours by name or index. Supports fuzzy name matching.
|
|
115
|
+
|
|
116
|
+
* `okabe-ito` (Default, colour-blind safe)
|
|
117
|
+
* `paul-tol-vibrant` | `paul-tol-bright` | `paul-tol-muted`
|
|
118
|
+
* `ibm`
|
|
119
|
+
* `tableau10`
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
p = osm.get_palette("vibrant")
|
|
123
|
+
color = p['red'] # Name access
|
|
124
|
+
color = p[0] # Index access (wraps around)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 3. Layout Control (`fixed_frame`)
|
|
128
|
+
|
|
129
|
+
A context manager for creating figures with precise axes placement.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
with osm.fixed_frame(figure_size=(5, 4)) as (fig, ax):
|
|
133
|
+
ax.scatter(data_x, data_y)
|
|
134
|
+
# Axes position is determined by internal fractions,
|
|
135
|
+
# ensuring consistent whitespace across different plots.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 4. TableMaker
|
|
139
|
+
|
|
140
|
+
Creates professional tables for results analysis. In Jupyter, renders a monochrome theme inspired by academic journals (booktabs style). In terminals, renders via `rich`.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
table = osm.TableMaker(
|
|
144
|
+
title="Performance Metrics",
|
|
145
|
+
columns=["Metric", "Result", "Unit"]
|
|
146
|
+
)
|
|
147
|
+
table.add_row("R-Squared", "0.9942", "—")
|
|
148
|
+
table.add_row("RMSE", "0.021", "m/s")
|
|
149
|
+
table.display()
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
For live updates during a loop (e.g. training), use `mode="live"`:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
table = osm.TableMaker(title="Training Log", columns=["Epoch", "Loss"], mode="live")
|
|
156
|
+
for epoch in range(10):
|
|
157
|
+
loss = train_one_epoch()
|
|
158
|
+
table.add_row(str(epoch), f"{loss:.4f}")
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 5. ProgressBar and `track()`
|
|
162
|
+
|
|
163
|
+
A static-HTML progress bar designed for Jupyter notebooks. Unlike `tqdm.auto`, it renders as plain `text/html` output — so the **completed bar is preserved when notebooks are committed to GitHub**, rather than showing an empty widget placeholder.
|
|
164
|
+
|
|
165
|
+
#### Simple iterator (tqdm-style)
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
for x in osm.track(range(1000), desc="Training"):
|
|
169
|
+
osm.sleep(0.001)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Context manager (manual `update`)
|
|
173
|
+
|
|
174
|
+
Use this when the loop body controls iteration (e.g. custom data loaders).
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
with osm.ProgressBar(total=N, desc="Sweep") as pb:
|
|
178
|
+
for i in range(N):
|
|
179
|
+
compute(i)
|
|
180
|
+
pb.update()
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Joblib parallel jobs
|
|
184
|
+
|
|
185
|
+
When using `joblib.Parallel`, pass `return_as="generator"` and wrap with `osm.track()`.
|
|
186
|
+
Results are yielded as each job completes, so the progress bar advances in real time.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from joblib import Parallel, delayed
|
|
190
|
+
|
|
191
|
+
def process(i):
|
|
192
|
+
osm.sleep(0.05) # simulate work
|
|
193
|
+
return i ** 2
|
|
194
|
+
|
|
195
|
+
results = list(
|
|
196
|
+
osm.track(
|
|
197
|
+
Parallel(n_jobs=-1, return_as="generator")(
|
|
198
|
+
delayed(process)(i) for i in range(100)
|
|
199
|
+
),
|
|
200
|
+
total=100,
|
|
201
|
+
desc="Parallel",
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
> **Note**: `return_as="generator"` requires joblib ≥ 1.2. The progress bar advances as
|
|
207
|
+
> jobs *complete*, not as they are dispatched — so the count accurately reflects finished work.
|
|
208
|
+
|
|
209
|
+
#### Key parameters
|
|
210
|
+
|
|
211
|
+
| Parameter | Default | Description |
|
|
212
|
+
|-----------|---------|-------------|
|
|
213
|
+
| `iterable` | `None` | Wrap any iterable for iterator-style use |
|
|
214
|
+
| `total` | `len(iterable)` | Total iterations (required when `iterable` has no `len`) |
|
|
215
|
+
| `desc` | `""` | Prefix label shown before the bar |
|
|
216
|
+
| `mininterval` | `0.1` s | Minimum time between HTML refreshes — prevents rendering from bottlenecking tight loops |
|
|
217
|
+
| `width` | `40` | Bar width in characters (terminal mode only) |
|
|
218
|
+
|
|
219
|
+
***
|
|
220
|
+
|
|
221
|
+
## API Reference
|
|
222
|
+
|
|
223
|
+
| Function / Class | Description |
|
|
224
|
+
|------------------|-------------|
|
|
225
|
+
| `set_style(...)` | Initialises global matplotlib parameters. |
|
|
226
|
+
| `reset_style()` | Restores matplotlib defaults. |
|
|
227
|
+
| `get_palette(name)` | Returns a `Palette` object with fuzzy name matching. |
|
|
228
|
+
| `build_color_map(labels)` | Maps a list of unique labels to palette colours. |
|
|
229
|
+
| `finalize(ax)` | Polishes the plot: legend frames, origin overlaps, optional grid/minor ticks. |
|
|
230
|
+
| `fixed_frame(...)` | Context manager for isolated figure styling with fixed axes placement. |
|
|
231
|
+
| `annotate_panels(axes)` | Automatically adds `(a)`, `(b)`, `(c)` labels to subplots. |
|
|
232
|
+
| `style_colorbar(cb)` | Applies publication styling to a colorbar. |
|
|
233
|
+
| `enable_minor_ticks(ax)` | Adds AutoMinorLocator ticks to both axes. |
|
|
234
|
+
| `apply_grid(ax)` | Adds a subtle dotted grid. |
|
|
235
|
+
| `TableMaker(...)` | Renders academic-style tables in the console or Jupyter. |
|
|
236
|
+
| `ProgressBar(...)` | Static-HTML progress bar; GitHub-safe in Jupyter. |
|
|
237
|
+
| `track(iterable)` | `tqdm`-style shorthand for `ProgressBar`. |
|
|
238
|
+
| `sleep(s)` | Re-export of `time.sleep` — avoids a separate import in notebooks. |
|
|
239
|
+
| `info()` | Prints version and dependency information. |
|
|
240
|
+
|
|
241
|
+
***
|
|
242
|
+
|
|
243
|
+
## Version History
|
|
244
|
+
|
|
245
|
+
* **v1.0.0 (24 Jul 2026)**: Initial Onsaemiro release, based on the final DataGraph 3.1.0 implementation.
|
|
246
|
+
|
|
247
|
+
***
|
|
248
|
+
|
|
249
|
+
*Created and maintained by Hanseul Kang.*
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# Onsaemiro
|
|
2
|
+
|
|
3
|
+
**Publication-quality matplotlib styling for Academic Research.**
|
|
4
|
+
|
|
5
|
+
Onsaemiro provides a streamlined interface for generating figures that meet the rigorous standards of scientific journals. It handles font scaling, consistent subplot positioning, colour-blind friendly palettes, and GitHub-safe progress bars — all with minimal boilerplate.
|
|
6
|
+
|
|
7
|
+
***
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
* **Fixed-Fraction Layout**: Prevents axes jumping between figures by enforcing consistent subplot dimensions.
|
|
12
|
+
* **Automatic Scaling**: Adjusts font sizes, line widths, and tick marks based on the physical figure width.
|
|
13
|
+
* **Academic Palettes**: Built-in support for Okabe-Ito, Paul Tol (Vibrant, Muted, Bright), and IBM palettes.
|
|
14
|
+
* **TableMaker**: Renders LaTeX-style "booktabs" tables directly in Jupyter notebooks or the terminal.
|
|
15
|
+
* **ProgressBar / `track()`**: Static-HTML progress bar that survives GitHub's notebook renderer — no ipywidgets required.
|
|
16
|
+
* **Context Management**: Use `fixed_frame` for one-off figures with specific dimensions without affecting global settings.
|
|
17
|
+
|
|
18
|
+
***
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Install Onsaemiro from PyPI:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install onsaemiro
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The package is published on PyPI and can also be installed directly from a local clone.
|
|
29
|
+
|
|
30
|
+
For local development, clone the repository, move into the package directory, and run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install -e .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The `-e` (editable) flag means changes to the Onsaemiro source are reflected immediately — no reinstall needed.
|
|
37
|
+
|
|
38
|
+
***
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import onsaemiro as osm
|
|
44
|
+
import matplotlib.pyplot as plt
|
|
45
|
+
import numpy as np
|
|
46
|
+
|
|
47
|
+
# 1. Global setup
|
|
48
|
+
osm.set_style(figure_size=(3.5, 2.5), palette="okabe-ito")
|
|
49
|
+
|
|
50
|
+
# 2. Get the palette
|
|
51
|
+
colors = osm.get_palette()
|
|
52
|
+
|
|
53
|
+
# 3. Plotting
|
|
54
|
+
x = np.linspace(0, 10, 100)
|
|
55
|
+
fig, ax = plt.subplots()
|
|
56
|
+
|
|
57
|
+
ax.plot(x, np.sin(x), color=colors['blue'], label='Signal A')
|
|
58
|
+
ax.plot(x, np.cos(x), color=colors['orange'], label='Signal B')
|
|
59
|
+
|
|
60
|
+
ax.set_xlabel('Time (s)')
|
|
61
|
+
ax.set_ylabel('Amplitude (V)')
|
|
62
|
+
ax.legend()
|
|
63
|
+
|
|
64
|
+
# 4. Finalise (handles legend borders and origin overlaps)
|
|
65
|
+
osm.finalize(ax)
|
|
66
|
+
plt.show()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
***
|
|
70
|
+
|
|
71
|
+
## Core Components
|
|
72
|
+
|
|
73
|
+
### 1. Global Styling (`set_style`)
|
|
74
|
+
|
|
75
|
+
Configures `plt.rcParams` for publication. Unlike standard matplotlib behaviour, it disables `autolayout` to ensure that labels do not shift the axes box. Defaults to a Times-style serif font.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
osm.set_style(
|
|
79
|
+
base_fontsize=12.5,
|
|
80
|
+
linewidth=1.2,
|
|
81
|
+
figure_size=(3.5, 2.5),
|
|
82
|
+
use_tex=False
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Colour Palettes (`Palette`)
|
|
87
|
+
|
|
88
|
+
Access colours by name or index. Supports fuzzy name matching.
|
|
89
|
+
|
|
90
|
+
* `okabe-ito` (Default, colour-blind safe)
|
|
91
|
+
* `paul-tol-vibrant` | `paul-tol-bright` | `paul-tol-muted`
|
|
92
|
+
* `ibm`
|
|
93
|
+
* `tableau10`
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
p = osm.get_palette("vibrant")
|
|
97
|
+
color = p['red'] # Name access
|
|
98
|
+
color = p[0] # Index access (wraps around)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Layout Control (`fixed_frame`)
|
|
102
|
+
|
|
103
|
+
A context manager for creating figures with precise axes placement.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
with osm.fixed_frame(figure_size=(5, 4)) as (fig, ax):
|
|
107
|
+
ax.scatter(data_x, data_y)
|
|
108
|
+
# Axes position is determined by internal fractions,
|
|
109
|
+
# ensuring consistent whitespace across different plots.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. TableMaker
|
|
113
|
+
|
|
114
|
+
Creates professional tables for results analysis. In Jupyter, renders a monochrome theme inspired by academic journals (booktabs style). In terminals, renders via `rich`.
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
table = osm.TableMaker(
|
|
118
|
+
title="Performance Metrics",
|
|
119
|
+
columns=["Metric", "Result", "Unit"]
|
|
120
|
+
)
|
|
121
|
+
table.add_row("R-Squared", "0.9942", "—")
|
|
122
|
+
table.add_row("RMSE", "0.021", "m/s")
|
|
123
|
+
table.display()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For live updates during a loop (e.g. training), use `mode="live"`:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
table = osm.TableMaker(title="Training Log", columns=["Epoch", "Loss"], mode="live")
|
|
130
|
+
for epoch in range(10):
|
|
131
|
+
loss = train_one_epoch()
|
|
132
|
+
table.add_row(str(epoch), f"{loss:.4f}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 5. ProgressBar and `track()`
|
|
136
|
+
|
|
137
|
+
A static-HTML progress bar designed for Jupyter notebooks. Unlike `tqdm.auto`, it renders as plain `text/html` output — so the **completed bar is preserved when notebooks are committed to GitHub**, rather than showing an empty widget placeholder.
|
|
138
|
+
|
|
139
|
+
#### Simple iterator (tqdm-style)
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
for x in osm.track(range(1000), desc="Training"):
|
|
143
|
+
osm.sleep(0.001)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Context manager (manual `update`)
|
|
147
|
+
|
|
148
|
+
Use this when the loop body controls iteration (e.g. custom data loaders).
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
with osm.ProgressBar(total=N, desc="Sweep") as pb:
|
|
152
|
+
for i in range(N):
|
|
153
|
+
compute(i)
|
|
154
|
+
pb.update()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### Joblib parallel jobs
|
|
158
|
+
|
|
159
|
+
When using `joblib.Parallel`, pass `return_as="generator"` and wrap with `osm.track()`.
|
|
160
|
+
Results are yielded as each job completes, so the progress bar advances in real time.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from joblib import Parallel, delayed
|
|
164
|
+
|
|
165
|
+
def process(i):
|
|
166
|
+
osm.sleep(0.05) # simulate work
|
|
167
|
+
return i ** 2
|
|
168
|
+
|
|
169
|
+
results = list(
|
|
170
|
+
osm.track(
|
|
171
|
+
Parallel(n_jobs=-1, return_as="generator")(
|
|
172
|
+
delayed(process)(i) for i in range(100)
|
|
173
|
+
),
|
|
174
|
+
total=100,
|
|
175
|
+
desc="Parallel",
|
|
176
|
+
)
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
> **Note**: `return_as="generator"` requires joblib ≥ 1.2. The progress bar advances as
|
|
181
|
+
> jobs *complete*, not as they are dispatched — so the count accurately reflects finished work.
|
|
182
|
+
|
|
183
|
+
#### Key parameters
|
|
184
|
+
|
|
185
|
+
| Parameter | Default | Description |
|
|
186
|
+
|-----------|---------|-------------|
|
|
187
|
+
| `iterable` | `None` | Wrap any iterable for iterator-style use |
|
|
188
|
+
| `total` | `len(iterable)` | Total iterations (required when `iterable` has no `len`) |
|
|
189
|
+
| `desc` | `""` | Prefix label shown before the bar |
|
|
190
|
+
| `mininterval` | `0.1` s | Minimum time between HTML refreshes — prevents rendering from bottlenecking tight loops |
|
|
191
|
+
| `width` | `40` | Bar width in characters (terminal mode only) |
|
|
192
|
+
|
|
193
|
+
***
|
|
194
|
+
|
|
195
|
+
## API Reference
|
|
196
|
+
|
|
197
|
+
| Function / Class | Description |
|
|
198
|
+
|------------------|-------------|
|
|
199
|
+
| `set_style(...)` | Initialises global matplotlib parameters. |
|
|
200
|
+
| `reset_style()` | Restores matplotlib defaults. |
|
|
201
|
+
| `get_palette(name)` | Returns a `Palette` object with fuzzy name matching. |
|
|
202
|
+
| `build_color_map(labels)` | Maps a list of unique labels to palette colours. |
|
|
203
|
+
| `finalize(ax)` | Polishes the plot: legend frames, origin overlaps, optional grid/minor ticks. |
|
|
204
|
+
| `fixed_frame(...)` | Context manager for isolated figure styling with fixed axes placement. |
|
|
205
|
+
| `annotate_panels(axes)` | Automatically adds `(a)`, `(b)`, `(c)` labels to subplots. |
|
|
206
|
+
| `style_colorbar(cb)` | Applies publication styling to a colorbar. |
|
|
207
|
+
| `enable_minor_ticks(ax)` | Adds AutoMinorLocator ticks to both axes. |
|
|
208
|
+
| `apply_grid(ax)` | Adds a subtle dotted grid. |
|
|
209
|
+
| `TableMaker(...)` | Renders academic-style tables in the console or Jupyter. |
|
|
210
|
+
| `ProgressBar(...)` | Static-HTML progress bar; GitHub-safe in Jupyter. |
|
|
211
|
+
| `track(iterable)` | `tqdm`-style shorthand for `ProgressBar`. |
|
|
212
|
+
| `sleep(s)` | Re-export of `time.sleep` — avoids a separate import in notebooks. |
|
|
213
|
+
| `info()` | Prints version and dependency information. |
|
|
214
|
+
|
|
215
|
+
***
|
|
216
|
+
|
|
217
|
+
## Version History
|
|
218
|
+
|
|
219
|
+
* **v1.0.0 (24 Jul 2026)**: Initial Onsaemiro release, based on the final DataGraph 3.1.0 implementation.
|
|
220
|
+
|
|
221
|
+
***
|
|
222
|
+
|
|
223
|
+
*Created and maintained by Hanseul Kang.*
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "onsaemiro"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Publication-quality scientific visualisation and reporting utilities"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Hanseul Kang", email = "hanseul.kang@aalto.fi"}
|
|
13
|
+
]
|
|
14
|
+
license = "MIT"
|
|
15
|
+
license-files = ["LICENSE"]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"numpy",
|
|
18
|
+
"matplotlib",
|
|
19
|
+
"rich",
|
|
20
|
+
"ipython",
|
|
21
|
+
]
|
|
22
|
+
keywords = [
|
|
23
|
+
"matplotlib",
|
|
24
|
+
"scientific-visualisation",
|
|
25
|
+
"publication",
|
|
26
|
+
"plotting",
|
|
27
|
+
"jupyter",
|
|
28
|
+
]
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Development Status :: 3 - Alpha",
|
|
31
|
+
"Intended Audience :: Science/Research",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Repository = "https://github.com/PentagonToy/Onsaemiro"
|
|
42
|
+
Issues = "https://github.com/PentagonToy/Onsaemiro/issues"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools]
|
|
45
|
+
package-dir = {"" = "src"}
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|