Metadata-Version: 2.5
Name: ieeeplot
Version: 0.2.0
Summary: Publication-ready scientific plots with IEEE-friendly Matplotlib defaults
Project-URL: Homepage, https://github.com/Abolfazl-Younesi/ieeeplot
Project-URL: Repository, https://github.com/Abolfazl-Younesi/ieeeplot
Project-URL: Issues, https://github.com/Abolfazl-Younesi/ieeeplot/issues
Author-email: Abolfazl Younesi <sa.younesi20@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: matplotlib>=3.9
Requires-Dist: numpy>=1.24
Requires-Dist: tomli>=2.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pandas>=1.5; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=5.1; extra == 'dev'
Provides-Extra: pandas
Requires-Dist: pandas>=1.5; extra == 'pandas'
Description-Content-Type: text/markdown

# ieeeplot

[![PyPI](https://img.shields.io/pypi/v/ieeeplot.svg)](https://pypi.org/project/ieeeplot/)
[![CI](https://github.com/Abolfazl-Younesi/ieeeplot/actions/workflows/ci.yml/badge.svg)](https://github.com/Abolfazl-Younesi/ieeeplot/actions/workflows/ci.yml)
[![Python versions](https://img.shields.io/pypi/pyversions/ieeeplot.svg)](https://pypi.org/project/ieeeplot/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

`ieeeplot` is a lightweight Python library for creating clean,
publication-ready scientific figures with IEEE-friendly defaults.

It is built on Matplotlib and intentionally stays close to the Matplotlib
API. The library handles common publication details such as figure
dimensions, typography, line styling, legends, and export settings while
still giving you direct access to the underlying Matplotlib figure and axes.

## Installation

```bash
pip install ieeeplot
```

Optional pandas support:

```bash
pip install "ieeeplot[pandas]"
```

## 30-second example

```python
import numpy as np
import ieeeplot as ip

x = np.linspace(0, 10, 200)
y = np.sin(x)

fig = ip.line(x, y, xlabel="Time (s)", ylabel="Amplitude")
fig.save("figure.pdf")
```

The output already has IEEE-friendly dimensions, readable fonts, sensible
line widths, and vector-friendly export — no manual Matplotlib tuning
required for a normal figure.

## Examples

<table>
<tr>
<td width="50%">

<img src="docs/images/line.png" alt="Multi-series line plot"/>

Multiple series get distinguishable color/marker/linestyle combinations
automatically — this is `ip.line(x, [measured, simulated], labels=[...])`
with no further styling.

</td>
<td width="50%">

<img src="docs/images/grayscale.png" alt="Grayscale-safe line plot"/>

The same idea under `ip.style("ieee-grayscale")`: every curve renders in
black, still distinguishable by marker and line style alone.

</td>
</tr>
<tr>
<td width="50%">

<img src="docs/images/boxplot.png" alt="Box plot comparing two distributions"/>

`ip.boxplot([baseline, proposed], labels=[...])` for comparing
distributions.

</td>
<td width="50%">

<img src="docs/images/polar.png" alt="Polar plot of a radiation pattern"/>

`ip.polar(theta, gain_db)` for radiation-pattern-style plots.

</td>
</tr>
</table>

<img src="docs/images/multi_panel.png" alt="Multi-panel figure with automatic panel labels"/>

`ip.subplots(rows=2, cols=2)` with `fig.add_panel_labels()` for automatic
(a)/(b)/(c)/(d) labels.

More runnable examples live in [examples/](examples/). The images above are
generated by [docs/images/generate.py](docs/images/generate.py).

## Plot types

```python
ip.line(x, y, ...)
ip.scatter(x, y, ...)
ip.errorbar(x, y, yerr=..., ...)
ip.bar(categories, values, ...)
ip.histogram(values, ...)
ip.boxplot(data, ...)
ip.violin(data, ...)
ip.heatmap(data, ...)
ip.contour(x, y, z, ...)
ip.polar(theta, r, ...)
fig, axes = ip.subplots(rows=2, cols=2, ...)
```

### Multiple series

```python
fig = ip.line(
    x,
    [measured, simulated],
    labels=["Measured", "Simulation"],
    xlabel="Time (s)",
    ylabel="Amplitude",
)
```

Multiple curves are automatically given distinguishable combinations of
color, marker, and line style, so figures remain readable when printed in
grayscale.

### Bar charts

```python
fig = ip.bar(
    ["A", "B", "C"],
    [[3, 5, 2], [4, 3, 6]],
    labels=["Baseline", "Proposed"],
    grouped=True,
)
```

### Distributions

```python
fig = ip.boxplot([baseline, proposed], labels=["Baseline", "Proposed"], ylabel="Error (dB)")
fig = ip.violin([baseline, proposed], labels=["Baseline", "Proposed"], ylabel="Error (dB)")
```

### Polar plots

```python
fig = ip.polar(theta, gain_db, title="Radiation pattern")
```

### Multi-panel figures

```python
fig, axes = ip.subplots(rows=2, cols=2, width="double-column")

axes[0, 0].plot(x, y1)
axes[0, 1].plot(x, y2)

fig.add_panel_labels()
fig.save("results.pdf")
```

## Figure sizing

```python
ip.line(x, y, width="single-column")  # 3.5 in
ip.line(x, y, width="double-column")  # 7.16 in
ip.line(x, y, width=4.2)  # custom width, inches
ip.line(x, y, width="single-column", height=2.4)
ip.line(x, y, width="single-column", aspect_ratio=1.6)
```

`height` defaults to `width / aspect_ratio` unless given explicitly.

## Styling

Styles are applied through `matplotlib.rc_context` and never permanently
change your global Matplotlib configuration.

```python
with ip.style("ieee-grayscale"):
    fig = ip.line(x, y)

fig = ip.line(x, y, config=ip.PlotConfig(style="ieee-color"))
```

Available styles: `ieee` (default), `ieee-color`, `ieee-grayscale`,
`presentation`.

Temporary configuration overrides:

```python
with ip.config(font_size=9, line_width=1.4):
    fig = ip.line(x, y)
```

### User-level defaults

Defaults can also be set once, outside your code, in
`~/.config/ieeeplot/config.toml`:

```toml
font_size = 9
line_width = 1.4
style = "ieee-color"
```

This is read once at import time and applied as the library-wide default,
underneath any `config=`/`ip.config()` overrides in your code. It's ignored
if the file doesn't exist.

## Exporting

```python
fig.save("result.pdf")
fig.save("result.svg")
fig.save("result.png", dpi=600)
```

Supported formats: `pdf`, `svg`, `eps`, `pgf` (vector), and `png`, `jpg`,
`jpeg`, `tiff` (raster, minimum 300 DPI by default). The format is inferred
from the file extension; an unsupported extension raises a clear error
instead of silently changing formats.

## Validation

```python
report = fig.check_ieee()
print(report.valid, report.warnings)
```

`check_ieee()` checks for common formatting issues — missing axis labels,
undersized fonts, low raster DPI, thin lines, oversized legends, and curves
that rely on color alone. It returns warnings; it never blocks saving, and
it does not guarantee acceptance by any venue. Treat it as formatting
guidance, not certification.

## Advanced Matplotlib customization

The underlying Matplotlib `Figure` and `Axes` are always reachable, so
nothing in `ieeeplot` blocks direct Matplotlib use:

```python
fig = ip.line(x, y)

fig.ax.axhline(0, linestyle=":", linewidth=0.8)
fig.ax.annotate("Operating point", xy=(4.2, 0.7))

fig.save("customized.pdf")
```

## Project status

`ieeeplot` is in early development (`0.x`). The public API may still
change between minor versions before `1.0`.

## License

MIT — see [LICENSE](LICENSE).
