Metadata-Version: 2.4
Name: timedatamodel
Version: 0.3.0
Summary: A lightweight data model for time series data with pandas, numpy, and polars support
Project-URL: Homepage, https://github.com/rebase-energy/TimeDataModel
Project-URL: Repository, https://github.com/rebase-energy/TimeDataModel
Project-URL: Issues, https://github.com/rebase-energy/TimeDataModel/issues
Author-email: Rebase Energy <sebastian@rebase.energy>
License: MIT
License-File: LICENSE
Keywords: data model,energy,numpy,pandas,polars,time series
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: polars>=1.0
Provides-Extra: all
Requires-Dist: numpy>=1.24; extra == 'all'
Requires-Dist: pandas>=2.0; extra == 'all'
Requires-Dist: pint>=0.24; extra == 'all'
Requires-Dist: pyarrow>=14.0; extra == 'all'
Requires-Dist: shapely>=2.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: numpy>=1.24; extra == 'dev'
Requires-Dist: pandas>=2.0; extra == 'dev'
Requires-Dist: pint>=0.24; extra == 'dev'
Requires-Dist: polars>=1.0; extra == 'dev'
Requires-Dist: pre-commit>=4.0; extra == 'dev'
Requires-Dist: pyarrow>=14.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: shapely>=2.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: ipykernel>=6.0; extra == 'docs'
Requires-Dist: myst-parser>=3.0; extra == 'docs'
Requires-Dist: nbsphinx>=0.9; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints>=2.3; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=3.0; extra == 'docs'
Requires-Dist: sphinx>=7.4; extra == 'docs'
Provides-Extra: geo
Requires-Dist: shapely>=2.0; extra == 'geo'
Provides-Extra: pandas
Requires-Dist: pandas>=2.0; extra == 'pandas'
Requires-Dist: pyarrow>=14.0; extra == 'pandas'
Provides-Extra: pint
Requires-Dist: pint>=0.24; extra == 'pint'
Description-Content-Type: text/markdown

<div align="center">

# TimeDataModel

**A lightweight Pythonic data model for time series data, interoperable with NumPy, Pandas and Polars.**

<a href="https://opensource.org/licenses/MIT"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square"></a>
<a href="https://pypi.org/project/timedatamodel/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/timedatamodel?color=blue&style=flat-square"></a>
<a href="https://pypi.org/project/timedatamodel/"><img alt="Python Versions" src="https://img.shields.io/pypi/pyversions/timedatamodel?style=flat-square"></a>
<a href="https://github.com/rebase-energy/TimeDataModel"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/rebase-energy/TimeDataModel?style=social"></a>

</div>

<br/>

**TimeDataModel** is a metadata-rich container for time series data. It lets you carry your data *and* its context — name, unit, frequency, timezone — as a single, self-describing object, fully interoperable with pandas, NumPy, Polars, and PyArrow.

**⬇️ [Installation](#installation)**
&ensp;|&ensp;
**📖 [Documentation](https://timedatamodel.readthedocs.io/en/latest/)**
&ensp;|&ensp;
**🚀 [Examples](https://timedatamodel.readthedocs.io/en/latest/examples/index.html)**

---

## 🧱 Core Data Classes

| Class | Description |
| :---- | :---------- |
| 📈&nbsp;`TimeSeries` | Univariate time series supporting four temporal shapes; the underlying DataFrame is optional, so the same class also serves as a metadata-only descriptor for catalog/registration use |
| 🔷&nbsp;`DataShape` | Enum that selects which timestamp columns are present: `SIMPLE`, `VERSIONED`, `CORRECTED`, or `AUDIT` |
| ⏱️&nbsp;`Frequency` | ISO 8601 duration-based frequencies (`PT1H`, `P1D`, `P1M`, …) |
| 🏷️&nbsp;`DataType` | Hierarchical taxonomy: `ACTUAL` → `OBSERVATION`, `DERIVED`; `CALCULATED` → `FORECAST`, `SIMULATION`, … |
| 🗺️&nbsp;`GeoLocation` / `GeoArea` | Geographic point and polygon types with distance, bearing, and containment |

---

## 📐 Data Shapes

`TimeSeries` supports four **temporal shapes** to model everything from simple point-in-time
data to fully bi-temporal audit trails:

| Shape | Columns | Use case |
| :---- | :------ | :------- |
| `SIMPLE` | `valid_time`, `value` | Standard time series |
| `VERSIONED` | `knowledge_time`, `valid_time`, `value` | Bi-temporal: track *when* each value was produced |
| `CORRECTED` | `valid_time`, `change_time`, `value` | Corrections: track *when* a value was revised |
| `AUDIT` | `knowledge_time`, `change_time`, `valid_time`, `value` | Full audit trail |

---

## 🚀 Quick Start

```python
import pandas as pd
from timedatamodel import TimeSeries, Frequency

# --- Univariate series from a pandas DataFrame ---
df = pd.DataFrame({
    "valid_time": pd.date_range("2024-01-01", periods=24, freq="h", tz="UTC"),
    "value": [100.0 + i * 2.5 for i in range(24)],
})

ts = TimeSeries.from_pandas(
    df,
    frequency=Frequency.PT1H,
    name="wind_power",
    unit="MW",
)

print(ts)
# TimeSeries ─────────────────────────
#   Name        wind_power
#   Shape       SIMPLE
#   Rows        24
#   Frequency   PT1H
#   Timezone    UTC
#   Unit        MW
#  ──────────────────────────────────────────
#                  wind_power
#  2024-01-01 00:00   100.0
#  2024-01-01 01:00   102.5
#  ...

# --- Unit conversion (requires pint extra) ---
ts_kw = ts.convert_unit("kW")

# --- Format conversions ---
df_pd  = ts.to_pandas()       # pd.DataFrame with datetime index
df_pl  = ts.to_polars()       # pl.DataFrame
cols   = ts.to_list()         # dict[str, list] — column-oriented
arr    = ts.to_numpy()        # dict[str, np.ndarray] — column-oriented (requires numpy)
tbl    = ts.to_pyarrow()      # pa.Table (requires pyarrow)
```

---

## ✨ Key Features

- 🔷 **Four data shapes** — from `SIMPLE` point-in-time to `AUDIT` full bi-temporal history;
- 🏷️ **Metadata** — name, unit, frequency, timezone, data type, description on every series;
- 📋 **Metadata-only mode** — construct `TimeSeries(df=None, …)` to declare a series' structure before any data exists, for catalog/registration use;
- 🔄 **Format conversions** — `to_pandas`, `to_polars`, `to_list`, `to_numpy`, `to_pyarrow` with lazy optional-dependency checks;
- 📊 **Coverage bar** — `coverage_bar()` renders null coverage as a binned SVG in Jupyter or Unicode blocks in terminal;
- 🗺️ **Geospatial primitives** — `GeoLocation` and `GeoArea` for use by consumer layers;
- 📏 **Units** — optional [pint](https://pint.readthedocs.io/) integration for dimensional unit conversion and validation;
- ⚡ **Polars-powered** — backed by the Polars compute engine for high-performance in-memory processing;
- 🐍 **Type-safe** — full type hints with PEP 561 support.

---

## ⬇️ Installation

Install the **stable** release:
```bash
pip install timedatamodel
```

Install with **optional dependencies**:
```bash
pip install timedatamodel[pandas]    # pandas interop (includes pyarrow for tz-aware columns)
pip install timedatamodel[pint]      # unit conversion
pip install timedatamodel[geo]       # geospatial support (shapely)
pip install timedatamodel[all]       # all optional extras
```

Install in editable mode for **development**:
```bash
git clone https://github.com/rebase-energy/TimeDataModel.git
cd TimeDataModel
pip install -e .[dev]
```

---

## 🤝 Contributing

Contributions are welcome! Here are some ways to contribute to **TimeDataModel**:

* Propose new features or extend existing classes;
* Improve documentation or add example notebooks;
* Report bugs or suggest features via [GitHub Issues](https://github.com/rebase-energy/TimeDataModel/issues).

---

## 📄 Licence

This project uses the [MIT Licence](LICENSE).
