Querying Data - PIPolars 0.1.0 documentation

Skip to content
Back to top
View this page
Edit this page

# Querying Data

PIPolars provides multiple ways to query data from PI System. This guide covers all the query methods and options.

## Query Methods Overview

PIPolars offers two approaches to querying:

1. Direct methods on `PIClient` - Simple, direct calls

2. Query builder (`PIQuery`) - Fluent, method-chaining interface

Both produce identical results; choose based on your preference.

## Direct Methods

### Snapshot Values

Get the current value of a tag:

    with PIClient("my-pi-server") as client:
        # Single tag
        df = client.snapshot("SINUSOID")

        # Multiple tags
        df = client.snapshots(["TAG1", "TAG2", "TAG3"])

### Recorded Values

Get actual archived values:

    with PIClient("my-pi-server") as client:
        # Basic query
        df = client.recorded_values(
            "SINUSOID",
            start="*-1d",
            end="*"
        )

        # With options
        df = client.recorded_values(
            "SINUSOID",
            start="*-1d",
            end="*",
            max_count=1000,          # Limit values
            include_quality=True,     # Add quality column
        )

        # Multiple tags
        df = client.recorded_values(
            ["TAG1", "TAG2", "TAG3"],
            start="*-1h",
            end="*",
            pivot=True  # Tags become columns
        )

### Interpolated Values

Get values at regular intervals:

    with PIClient("my-pi-server") as client:
        # Hourly interpolation
        df = client.interpolated_values(
            "SINUSOID",
            start="*-1d",
            end="*",
            interval="1h"
        )

        # 15-minute intervals
        df = client.interpolated_values(
            "SINUSOID",
            start="*-4h",
            end="*",
            interval="15m"
        )

        # Multiple tags, pivoted
        df = client.interpolated_values(
            ["TAG1", "TAG2"],
            start="*-2h",
            end="*",
            interval="10m",
            pivot=True
        )

### Plot Values

Get values optimized for plotting (reduced density):

    with PIClient("my-pi-server") as client:
        df = client.plot_values(
            "SINUSOID",
            start="*-7d",
            end="*",
            intervals=640  # Number of plot points
        )

### Summary Values

Calculate statistics over a time range:

    from pipolars import SummaryType

    with PIClient("my-pi-server") as client:
        # Single summary over entire range
        df = client.summary(
            "SINUSOID",
            start="*-7d",
            end="*",
            summary_types=[
                SummaryType.AVERAGE,
                SummaryType.MINIMUM,
                SummaryType.MAXIMUM
            ]
        )

        # Time-series summaries (e.g., hourly averages)
        df = client.summaries(
            "SINUSOID",
            start="*-1d",
            end="*",
            interval="1h",
            summary_types=SummaryType.AVERAGE
        )

## Query Builder (Fluent API)

The query builder provides a readable, chainable interface:

### Basic Usage

    with PIClient("my-pi-server") as client:
        df = (
            client.query("SINUSOID")
            .time_range("*-1d", "*")
            .recorded()
            .to_dataframe()
        )

### Time Range Methods

    # Explicit time range
    query.time_range("*-1d", "*")

    # Last N time units
    query.last(hours=24)
    query.last(days=7)
    query.last(minutes=30)
    query.last(hours=2, minutes=30)

    # Preset ranges
    query.today()
    query.yesterday()
    query.this_week()
    query.this_month()

### Query Type Methods

    # Recorded values
    query.recorded()
    query.recorded(max_count=1000)

    # Interpolated values
    query.interpolated(interval="1h")
    query.interpolated(interval="15m")

    # Plot-optimized
    query.plot(intervals=640)

    # Summary statistics
    query.summary(SummaryType.AVERAGE)
    query.summary(SummaryType.AVERAGE, SummaryType.MAXIMUM)

    # Current snapshot
    query.snapshot()

### Option Methods

    # Include quality information
    query.with_quality()

    # Pivot to wide format
    query.pivot()

    # Limit results
    query.limit(1000)

### Execution Methods

    # Get DataFrame
    df = query.to_dataframe()

    # Get LazyFrame (for deferred execution)
    lf = query.to_lazy_frame()

### Complete Examples

    from pipolars import PIClient, SummaryType

    with PIClient("my-pi-server") as client:
        # Example 1: 24 hours of interpolated data with quality
        df = (
            client.query("SINUSOID")
            .last(hours=24)
            .interpolated(interval="15m")
            .with_quality()
            .to_dataframe()
        )

        # Example 2: Multiple tags, pivoted
        df = (
            client.query(["TAG1", "TAG2", "TAG3"])
            .time_range("*-4h", "*")
            .interpolated(interval="10m")
            .pivot()
            .to_dataframe()
        )

        # Example 3: Weekly summary statistics
        df = (
            client.query("SINUSOID")
            .last(days=7)
            .summary(
                SummaryType.AVERAGE,
                SummaryType.MINIMUM,
                SummaryType.MAXIMUM,
                SummaryType.STD_DEV
            )
            .to_dataframe()
        )

        # Example 4: Today's snapshots
        df = (
            client.query(["TAG1", "TAG2"])
            .today()
            .recorded()
            .to_dataframe()
        )

## Convenience Methods

PIPolars provides shortcut methods for common queries:

    with PIClient("my-pi-server") as client:
        # Get last N hours/days/minutes
        df = client.last("SINUSOID", hours=24)
        df = client.last("SINUSOID", days=7)
        df = client.last(["TAG1", "TAG2"], hours=4)

        # Get today's data
        df = client.today("SINUSOID")
        df = client.today(["TAG1", "TAG2"])

## Tag Operations

### Searching for Tags

    with PIClient("my-pi-server") as client:
        # Wildcard search
        tags = client.search_tags("SINU*")
        tags = client.search_tags("*TEMP*")
        tags = client.search_tags("UNIT1.*")

        # Limit results
        tags = client.search_tags("*", max_results=100)

### Checking Tag Existence

    with PIClient("my-pi-server") as client:
        if client.tag_exists("SINUSOID"):
            df = client.snapshot("SINUSOID")

### Tag Information

    with PIClient("my-pi-server") as client:
        info = client.tag_info("SINUSOID")
        print(info)
        # {
        #     'name': 'SINUSOID',
        #     'point_id': 1234,
        #     'point_type': 'float64',
        #     'description': 'Demo sinusoid tag',
        #     'engineering_units': '',
        #     'zero': 0.0,
        #     'span': 100.0
        # }

## Output Format Options

### Wide vs Long Format

By default, multi-tag queries return data in “long” format:

    shape: (100, 3)
    +-------------------------+----------+-------+
    | timestamp               | tag      | value |
    | ---                     | ---      | ---   |
    | datetime[us, UTC]       | str      | f64   |
    +-------------------------+----------+-------+
    | 2024-01-15 10:00:00 UTC | TAG1     | 50.5  |
    | 2024-01-15 10:00:00 UTC | TAG2     | 75.2  |
    | 2024-01-15 10:15:00 UTC | TAG1     | 51.3  |
    ...

Use `pivot=True` for “wide” format:

    shape: (50, 3)
    +-------------------------+-------+-------+
    | timestamp               | TAG1  | TAG2  |
    | ---                     | ---   | ---   |
    | datetime[us, UTC]       | f64   | f64   |
    +-------------------------+-------+-------+
    | 2024-01-15 10:00:00 UTC | 50.5  | 75.2  |
    | 2024-01-15 10:15:00 UTC | 51.3  | 76.1  |
    ...

### Quality Information

Include quality flags with `include_quality=True`:

    df = client.recorded_values(
        "SINUSOID",
        start="*-1h",
        end="*",
        include_quality=True
    )

Output:

    shape: (100, 3)
    +-------------------------+-------+---------+
    | timestamp               | value | quality |
    | ---                     | ---   | ---     |
    | datetime[us, UTC]       | f64   | i8      |
    +-------------------------+-------+---------+
    | 2024-01-15 10:00:00 UTC | 50.5  | 0       |
    | 2024-01-15 10:01:00 UTC | 51.2  | 0       |
    ...

Quality values:

- 0: Good

- 1: Substituted

- 2: Questionable

- 3: Bad

- 4: No Data

- 5: Calculation Failed

## Next Steps

- Time Expressions - Detailed time expression syntax

- Working with Polars DataFrames - Working with Polars DataFrames

- PIQuery - PIQuery API reference