Skip to main content

High-performance PI System data extraction library with Polars DataFrames

Project description

PIPolars

High-performance PI System data extraction library with Polars DataFrames.

PIPolars is a modern Python library for extracting data from OSIsoft PI System and converting it to Polars DataFrames for efficient data science workflows. It's designed to be faster, more memory-efficient, and more Pythonic than existing alternatives.

Features

  • Polars DataFrames: 10-100x faster than pandas for many operations
  • Modern Python: Full type hints, Pydantic configuration, Python 3.10+
  • Efficient Bulk Operations: Native bulk API support for extracting multiple tags
  • Lazy Evaluation: Polars LazyFrame support for query optimization
  • Caching: SQLite and Arrow IPC caching for reduced server load
  • Fluent Query API: Method chaining for readable, declarative queries
  • uv Compatible: Modern package management with Astral's uv

Requirements

  • Python 3.10+
  • Windows (for PI AF SDK)
  • OSIsoft PI AF SDK 2.x (.NET 4.8)

Installation

Using uv (recommended)

uv add pipolars

Using pip

pip install pipolars

Development Installation

git clone https://github.com/pipolars/pipolars.git
cd pipolars
uv sync

Quick Start

Basic Usage

from pipolars import PIClient

# Connect to PI Server
with PIClient("my-pi-server") as client:
    # Get current value
    df = client.snapshot("SINUSOID")
    print(df)

    # Get last 24 hours of data
    df = client.recorded_values("SINUSOID", start="*-1d", end="*")
    print(f"Retrieved {len(df)} values")

    # Get multiple tags at once
    df = client.recorded_values(
        ["TAG1", "TAG2", "TAG3"],
        start="*-1h",
        end="*",
    )

Query Builder (Fluent API)

from pipolars import PIClient, SummaryType

with PIClient("my-pi-server") as client:
    # Fluent query building
    df = (
        client.query("SINUSOID")
        .last(hours=24)
        .interpolated(interval="15m")
        .with_quality()
        .to_dataframe()
    )

    # Multi-tag query with pivot
    df = (
        client.query(["TAG1", "TAG2", "TAG3"])
        .time_range("*-1d", "*")
        .interpolated(interval="1h")
        .pivot()  # Tags become columns
        .to_dataframe()
    )

    # Summary statistics
    df = (
        client.query("SINUSOID")
        .last(days=7)
        .summary(SummaryType.AVERAGE, SummaryType.MAXIMUM, SummaryType.MINIMUM)
        .to_dataframe()
    )

Data Processing with Polars

import polars as pl
from pipolars import PIClient

with PIClient("my-pi-server") as client:
    # Get data
    df = client.interpolated_values("SINUSOID", "*-1d", "*", interval="5m")

    # Process with Polars
    result = (
        df.with_columns([
            pl.col("value").rolling_mean(window_size=12).alias("rolling_avg"),
            pl.col("value").diff().alias("change"),
        ])
        .filter(pl.col("value") > 50)
    )

Caching

from pipolars import PIClient, PIConfig
from pipolars.core.config import CacheBackend, CacheConfig, PIServerConfig

# Configure with SQLite cache
config = PIConfig(
    server=PIServerConfig(host="my-pi-server"),
    cache=CacheConfig(
        backend=CacheBackend.SQLITE,
        ttl_hours=24,
    ),
)

with PIClient(config=config) as client:
    # First query - fetches from PI
    df1 = client.recorded_values("SINUSOID", "*-1h", "*")

    # Second query - from cache (faster)
    df2 = client.recorded_values("SINUSOID", "*-1h", "*")

    # Check cache stats
    print(client.cache_stats())

Standalone Script with uv

You can run PIPolars scripts with uv's inline dependencies:

#!/usr/bin/env python3
# /// script
# requires-python = ">=3.10"
# dependencies = ["pipolars"]
# ///

from pipolars import PIClient

with PIClient("my-pi-server") as client:
    df = client.last("SINUSOID", hours=24)
    print(df.describe())

Run with:

uv run my_script.py

Configuration

Environment Variables

# PI Server configuration
PI_SERVER_HOST=my-pi-server
PI_SERVER_PORT=5450
PI_SERVER_TIMEOUT=30

# Cache configuration
PIPOLARS_CACHE_BACKEND=sqlite
PIPOLARS_CACHE_TTL_HOURS=24

# Polars configuration
PIPOLARS_POLARS_TIMEZONE=America/New_York

Configuration File

from pipolars import PIConfig

config = PIConfig.from_file("config.toml")

API Reference

PIClient

Main client for PI data extraction.

Method Description
snapshot(tag) Get current value
snapshots(tags) Get current values for multiple tags
recorded_values(tags, start, end) Get recorded values
interpolated_values(tags, start, end, interval) Get interpolated values
plot_values(tag, start, end, intervals) Get plot-optimized values
summary(tags, start, end, summary_types) Get summary statistics
summaries(tag, start, end, interval, summary_types) Get interval summaries
query(tags) Start building a query
last(tags, hours, days, minutes) Convenience method for recent data
today(tags) Get today's data

Time Expressions

PIPolars supports PI time expressions:

Expression Description
* Now
*-1h 1 hour ago
*-1d 1 day ago
t Today at midnight
y Yesterday at midnight
2024-01-15 Absolute date
2024-01-15T10:00:00 Absolute datetime

Summary Types

from pipolars import SummaryType

SummaryType.TOTAL      # Sum of values
SummaryType.AVERAGE    # Time-weighted average
SummaryType.MINIMUM    # Minimum value
SummaryType.MAXIMUM    # Maximum value
SummaryType.RANGE      # Max - Min
SummaryType.STD_DEV    # Standard deviation
SummaryType.COUNT      # Number of values
SummaryType.PERCENT_GOOD  # Percentage of good values

Comparison with PIconnect

Feature PIconnect PIPolars
DataFrame output pandas Polars (faster)
Bulk operations Limited Native bulk API
Lazy evaluation No Yes (LazyFrame)
Caching No SQLite + Arrow
Type hints Partial Full coverage
Async support No Optional async
Package manager pip uv compatible
Memory efficiency Medium High (zero-copy)
Query builder Basic Fluent API

Development

Setup

# Clone the repository
git clone https://github.com/pipolars/pipolars.git
cd pipolars

# Install with dev dependencies
uv sync --all-extras

# Run tests
uv run pytest

# Run type checking
uv run mypy src

# Run linting
uv run ruff check src

Running Tests

# Unit tests only
uv run pytest tests/unit

# Integration tests (requires PI connection)
PI_SERVER=my-server uv run pytest -m integration

# With coverage
uv run pytest --cov=pipolars --cov-report=html

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please see our Contributing Guide for details.

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pipolars-0.1.1.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pipolars-0.1.1-py3-none-any.whl (66.8 kB view details)

Uploaded Python 3

File details

Details for the file pipolars-0.1.1.tar.gz.

File metadata

  • Download URL: pipolars-0.1.1.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pipolars-0.1.1.tar.gz
Algorithm Hash digest
SHA256 956419225ad39ecc8c297ed79047009bfc6b5b2e6360108c302a0271294246a3
MD5 de629aa3f915a58ebd6ed08ea205431a
BLAKE2b-256 62da770e783df0e1f739670a6fe95b40c2e8f22f33e0e85bb375b668c9f1d2a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipolars-0.1.1.tar.gz:

Publisher: publish.yml on aserdargun/pipolars

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pipolars-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pipolars-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 66.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pipolars-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 59a497e49df0176338629c5a5c5e4eb035b85c9565ea58f8d99c2239bb2bb330
MD5 b2e81661f51cd14e8683ef598ccf52e0
BLAKE2b-256 13b679afce7c13942b49972421c71d68cfef11431e11124db21fe96d41451f26

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipolars-0.1.1-py3-none-any.whl:

Publisher: publish.yml on aserdargun/pipolars

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page