Skip to content

SQL API

SQLite output database parsing and query interface.

SQLResult

idfkit.simulation.parsers.sql.SQLResult

Query interface for an EnergyPlus SQLite output database.

Opens the database in read-only mode and provides methods for retrieving time-series data, tabular reports, and variable metadata.

Can be used as a context manager:

```python
with SQLResult("eplusout.sql") as sql:
    ts = sql.get_timeseries("Zone Mean Air Temperature", "ZONE 1")
```
Source code in src/idfkit/simulation/parsers/sql.py
class SQLResult:
    """Query interface for an EnergyPlus SQLite output database.

    Opens the database in read-only mode and provides methods for retrieving
    time-series data, tabular reports, and variable metadata.

    Can be used as a context manager:

        ```python
        with SQLResult("eplusout.sql") as sql:
            ts = sql.get_timeseries("Zone Mean Air Temperature", "ZONE 1")
        ```
    """

    def __init__(self, db_path: str | Path) -> None:
        """Open the SQLite database in read-only mode.

        Args:
            db_path: Path to the EnergyPlus ``.sql`` output file.
        """
        self._db_path = Path(db_path)
        self._conn = sqlite3.connect(f"file:{self._db_path}?mode=ro", uri=True)

    def close(self) -> None:
        """Close the database connection."""
        self._conn.close()

    def __enter__(self) -> SQLResult:
        return self

    def __exit__(self, *exc: object) -> None:
        self.close()

    def get_timeseries(
        self,
        variable_name: str,
        key_value: str = "*",
        frequency: str | None = None,
        environment: Environment | None = None,
    ) -> TimeSeriesResult:
        """Retrieve a time series for a variable.

        Args:
            variable_name: The output variable name.
            key_value: The key value (e.g. zone name). Use ``"*"`` for
                environment-level variables. Case-insensitive matching.
            frequency: Optional frequency filter (e.g. ``"Hourly"``).
            environment: Filter by environment type. ``None`` (default)
                returns all data, ``"annual"`` returns only weather-file
                run period data, and ``"sizing"`` returns only design-day data.

        Returns:
            A TimeSeriesResult with timestamps and values.

        Raises:
            KeyError: If the variable is not found in the database.
            ValueError: If *environment* is not a recognized value.
        """
        cur = self._conn.cursor()

        # Find the matching ReportDataDictionary entry
        query = (
            "SELECT rdd.ReportDataDictionaryIndex, rdd.Name, rdd.KeyValue, rdd.Units "
            "FROM ReportDataDictionary rdd "
            "WHERE rdd.Name = ?"
        )
        params: list[object] = [variable_name]

        if key_value != "*":
            query += " AND UPPER(rdd.KeyValue) = UPPER(?)"
            params.append(key_value)

        if frequency is not None:
            query += " AND rdd.ReportingFrequency = ?"
            params.append(frequency)

        cur.execute(query, params)
        row = cur.fetchone()
        if row is None:
            raise KeyError(f"Variable not found: {variable_name!r} (key={key_value!r})")  # noqa: TRY003

        rdd_index, name, key_val, units = row

        # Get the reporting frequency
        cur.execute(
            "SELECT ReportingFrequency FROM ReportDataDictionary WHERE ReportDataDictionaryIndex = ?",
            (rdd_index,),
        )
        freq_row = cur.fetchone()
        raw_freq: str = str(freq_row[0]) if freq_row else ""
        freq: str = _FREQUENCY_MAP.get(raw_freq, raw_freq) if raw_freq else "Unknown"

        # Retrieve time-series data, filtering out warmup periods.
        # COALESCE handles EnergyPlus versions where WarmupFlag is NULL.
        ts_query = (
            "SELECT t.Year, t.Month, t.Day, t.Hour, t.Minute, rd.Value "
            "FROM ReportData rd "
            "JOIN Time t ON rd.TimeIndex = t.TimeIndex "
        )
        ts_params: list[object] = [rdd_index]
        conditions = [
            "rd.ReportDataDictionaryIndex = ?",
            "COALESCE(t.WarmupFlag, 0) = 0",
        ]

        if environment is not None:
            ts_query += "JOIN EnvironmentPeriods ep ON t.EnvironmentPeriodIndex = ep.EnvironmentPeriodIndex "
            if environment == "sizing":
                conditions.append(f"ep.EnvironmentType IN ({', '.join('?' for _ in _SIZING_ENV_TYPES)})")
                ts_params.extend(_SIZING_ENV_TYPES)
            elif environment == "annual":
                conditions.append("ep.EnvironmentType = ?")
                ts_params.append(_ANNUAL_ENV_TYPE)
            else:
                msg = f"environment must be 'sizing', 'annual', or None, got {environment!r}"
                raise ValueError(msg)

        ts_query += "WHERE " + " AND ".join(conditions) + " ORDER BY t.TimeIndex"
        cur.execute(ts_query, ts_params)

        timestamps: list[datetime] = []
        values: list[float] = []
        for year, month, day, hour, minute, value in cur.fetchall():
            ref_year = year if year and year > 0 else _REFERENCE_YEAR
            timestamps.append(_make_timestamp(ref_year, month, day, hour, minute))
            values.append(float(value))

        return TimeSeriesResult(
            variable_name=name,
            key_value=key_val,
            units=units,
            frequency=freq,
            timestamps=tuple(timestamps),
            values=tuple(values),
        )

    def get_tabular_data(
        self,
        report_name: str | None = None,
        table_name: str | None = None,
        row_name: str | None = None,
        column_name: str | None = None,
        report_for: str | None = None,
    ) -> list[TabularRow]:
        """Retrieve tabular report data.

        Args:
            report_name: Optional filter by report name.
            table_name: Optional filter by table name.
            row_name: Optional filter by row label.
            column_name: Optional filter by column label.
            report_for: Optional filter by report scope (e.g. ``"Entire Facility"``).

        Returns:
            List of TabularRow entries matching the filters.
        """
        query = (
            "SELECT ReportName, ReportForString, TableName, RowName, "
            "ColumnName, Units, Value "
            "FROM TabularDataWithStrings"
        )
        conditions: list[str] = []
        params: list[str] = []

        if report_name is not None:
            conditions.append("ReportName = ?")
            params.append(report_name)
        if table_name is not None:
            conditions.append("TableName = ?")
            params.append(table_name)
        if row_name is not None:
            conditions.append("RowName = ?")
            params.append(row_name)
        if column_name is not None:
            conditions.append("ColumnName = ?")
            params.append(column_name)
        if report_for is not None:
            conditions.append("ReportForString = ?")
            params.append(report_for)

        if conditions:
            query += " WHERE " + " AND ".join(conditions)

        cur = self._conn.cursor()
        cur.execute(query, params)

        return [
            TabularRow(
                report_name=row[0],
                report_for=row[1],
                table_name=row[2],
                row_name=row[3],
                column_name=row[4],
                units=row[5],
                value=row[6],
            )
            for row in cur.fetchall()
        ]

    def get_tabular_value(
        self,
        report_name: str,
        table_name: str,
        row_name: str,
        column_name: str,
        report_for: str = "Entire Facility",
    ) -> str:
        """Retrieve a single tabular cell value.

        Convenience wrapper around [get_tabular_data][idfkit.simulation.parsers.sql.SQLResult.get_tabular_data] that returns
        exactly one cell value.

        Args:
            report_name: Report name (e.g. ``"AnnualBuildingUtilityPerformanceSummary"``).
            table_name: Table name (e.g. ``"End Uses"``).
            row_name: Row label (e.g. ``"Heating"``).
            column_name: Column label (e.g. ``"Electricity"``).
            report_for: Report scope (default ``"Entire Facility"``).

        Returns:
            The cell value as a string.

        Raises:
            KeyError: If no matching row is found or if multiple rows match.
        """
        rows = self.get_tabular_data(
            report_name=report_name,
            table_name=table_name,
            row_name=row_name,
            column_name=column_name,
            report_for=report_for,
        )
        if len(rows) == 0:
            msg = (
                f"No tabular data found: report={report_name!r}, table={table_name!r}, "
                f"row={row_name!r}, column={column_name!r}"
            )
            raise KeyError(msg)
        if len(rows) > 1:
            msg = (
                f"Multiple rows found ({len(rows)}): report={report_name!r}, table={table_name!r}, "
                f"row={row_name!r}, column={column_name!r}"
            )
            raise KeyError(msg)
        return rows[0].value

    def list_variables(self) -> list[VariableInfo]:
        """List all available variables in the database.

        Returns:
            List of VariableInfo entries describing each variable.
        """
        cur = self._conn.cursor()
        cur.execute("SELECT Name, KeyValue, ReportingFrequency, Units, IsMeter, Type FROM ReportDataDictionary")

        return [
            VariableInfo(
                name=str(row[0]),
                key_value=str(row[1]),
                frequency=_FREQUENCY_MAP.get(str(row[2]), str(row[2])),
                units=str(row[3]),
                is_meter=bool(row[4]),
                variable_type=str(row[5]) if row[5] else "",
            )
            for row in cur.fetchall()
        ]

    def list_environments(self) -> list[EnvironmentInfo]:
        """List all environment periods in the database.

        Returns:
            List of EnvironmentInfo entries describing each period (e.g.
            design days and run periods).
        """
        cur = self._conn.cursor()
        cur.execute(
            "SELECT EnvironmentPeriodIndex, EnvironmentName, EnvironmentType "
            "FROM EnvironmentPeriods ORDER BY EnvironmentPeriodIndex"
        )
        return [EnvironmentInfo(index=row[0], name=str(row[1]), environment_type=row[2]) for row in cur.fetchall()]

    def list_reports(self) -> list[str]:
        """List all available tabular report names.

        Returns:
            Sorted list of unique report names.
        """
        cur = self._conn.cursor()
        cur.execute("SELECT DISTINCT ReportName FROM TabularDataWithStrings ORDER BY ReportName")
        return [row[0] for row in cur.fetchall()]

    def to_dataframe(
        self,
        variable_name: str,
        key_value: str = "*",
        frequency: str | None = None,
        environment: Environment | None = None,
    ) -> Any:
        """Retrieve a time series as a pandas DataFrame.

        This is a convenience wrapper around [get_timeseries][idfkit.simulation.parsers.sql.SQLResult.get_timeseries] that
        directly returns a DataFrame.

        Args:
            variable_name: The output variable name.
            key_value: The key value. Use ``"*"`` for environment-level variables.
            frequency: Optional frequency filter.
            environment: Filter by environment type (``None`` by default
                for all data, ``"annual"`` for run periods, ``"sizing"`` for
                design days).

        Returns:
            A pandas DataFrame with a ``timestamp`` index.

        Raises:
            ImportError: If pandas is not installed.
            KeyError: If the variable is not found.
        """
        ts = self.get_timeseries(variable_name, key_value, frequency, environment)
        return ts.to_dataframe()

    def query(self, sql: str, parameters: tuple[object, ...] = ()) -> list[tuple[object, ...]]:
        """Execute a raw SQL query.

        Args:
            sql: The SQL query string.
            parameters: Query parameters for parameterized queries.

        Returns:
            List of result tuples.
        """
        cur = self._conn.cursor()
        cur.execute(sql, parameters)
        return cur.fetchall()

get_timeseries(variable_name, key_value='*', frequency=None, environment=None)

Retrieve a time series for a variable.

Parameters:

Name Type Description Default
variable_name str

The output variable name.

required
key_value str

The key value (e.g. zone name). Use "*" for environment-level variables. Case-insensitive matching.

'*'
frequency str | None

Optional frequency filter (e.g. "Hourly").

None
environment Environment | None

Filter by environment type. None (default) returns all data, "annual" returns only weather-file run period data, and "sizing" returns only design-day data.

None

Returns:

Type Description
TimeSeriesResult

A TimeSeriesResult with timestamps and values.

Raises:

Type Description
KeyError

If the variable is not found in the database.

ValueError

If environment is not a recognized value.

Source code in src/idfkit/simulation/parsers/sql.py
def get_timeseries(
    self,
    variable_name: str,
    key_value: str = "*",
    frequency: str | None = None,
    environment: Environment | None = None,
) -> TimeSeriesResult:
    """Retrieve a time series for a variable.

    Args:
        variable_name: The output variable name.
        key_value: The key value (e.g. zone name). Use ``"*"`` for
            environment-level variables. Case-insensitive matching.
        frequency: Optional frequency filter (e.g. ``"Hourly"``).
        environment: Filter by environment type. ``None`` (default)
            returns all data, ``"annual"`` returns only weather-file
            run period data, and ``"sizing"`` returns only design-day data.

    Returns:
        A TimeSeriesResult with timestamps and values.

    Raises:
        KeyError: If the variable is not found in the database.
        ValueError: If *environment* is not a recognized value.
    """
    cur = self._conn.cursor()

    # Find the matching ReportDataDictionary entry
    query = (
        "SELECT rdd.ReportDataDictionaryIndex, rdd.Name, rdd.KeyValue, rdd.Units "
        "FROM ReportDataDictionary rdd "
        "WHERE rdd.Name = ?"
    )
    params: list[object] = [variable_name]

    if key_value != "*":
        query += " AND UPPER(rdd.KeyValue) = UPPER(?)"
        params.append(key_value)

    if frequency is not None:
        query += " AND rdd.ReportingFrequency = ?"
        params.append(frequency)

    cur.execute(query, params)
    row = cur.fetchone()
    if row is None:
        raise KeyError(f"Variable not found: {variable_name!r} (key={key_value!r})")  # noqa: TRY003

    rdd_index, name, key_val, units = row

    # Get the reporting frequency
    cur.execute(
        "SELECT ReportingFrequency FROM ReportDataDictionary WHERE ReportDataDictionaryIndex = ?",
        (rdd_index,),
    )
    freq_row = cur.fetchone()
    raw_freq: str = str(freq_row[0]) if freq_row else ""
    freq: str = _FREQUENCY_MAP.get(raw_freq, raw_freq) if raw_freq else "Unknown"

    # Retrieve time-series data, filtering out warmup periods.
    # COALESCE handles EnergyPlus versions where WarmupFlag is NULL.
    ts_query = (
        "SELECT t.Year, t.Month, t.Day, t.Hour, t.Minute, rd.Value "
        "FROM ReportData rd "
        "JOIN Time t ON rd.TimeIndex = t.TimeIndex "
    )
    ts_params: list[object] = [rdd_index]
    conditions = [
        "rd.ReportDataDictionaryIndex = ?",
        "COALESCE(t.WarmupFlag, 0) = 0",
    ]

    if environment is not None:
        ts_query += "JOIN EnvironmentPeriods ep ON t.EnvironmentPeriodIndex = ep.EnvironmentPeriodIndex "
        if environment == "sizing":
            conditions.append(f"ep.EnvironmentType IN ({', '.join('?' for _ in _SIZING_ENV_TYPES)})")
            ts_params.extend(_SIZING_ENV_TYPES)
        elif environment == "annual":
            conditions.append("ep.EnvironmentType = ?")
            ts_params.append(_ANNUAL_ENV_TYPE)
        else:
            msg = f"environment must be 'sizing', 'annual', or None, got {environment!r}"
            raise ValueError(msg)

    ts_query += "WHERE " + " AND ".join(conditions) + " ORDER BY t.TimeIndex"
    cur.execute(ts_query, ts_params)

    timestamps: list[datetime] = []
    values: list[float] = []
    for year, month, day, hour, minute, value in cur.fetchall():
        ref_year = year if year and year > 0 else _REFERENCE_YEAR
        timestamps.append(_make_timestamp(ref_year, month, day, hour, minute))
        values.append(float(value))

    return TimeSeriesResult(
        variable_name=name,
        key_value=key_val,
        units=units,
        frequency=freq,
        timestamps=tuple(timestamps),
        values=tuple(values),
    )

get_tabular_data(report_name=None, table_name=None, row_name=None, column_name=None, report_for=None)

Retrieve tabular report data.

Parameters:

Name Type Description Default
report_name str | None

Optional filter by report name.

None
table_name str | None

Optional filter by table name.

None
row_name str | None

Optional filter by row label.

None
column_name str | None

Optional filter by column label.

None
report_for str | None

Optional filter by report scope (e.g. "Entire Facility").

None

Returns:

Type Description
list[TabularRow]

List of TabularRow entries matching the filters.

Source code in src/idfkit/simulation/parsers/sql.py
def get_tabular_data(
    self,
    report_name: str | None = None,
    table_name: str | None = None,
    row_name: str | None = None,
    column_name: str | None = None,
    report_for: str | None = None,
) -> list[TabularRow]:
    """Retrieve tabular report data.

    Args:
        report_name: Optional filter by report name.
        table_name: Optional filter by table name.
        row_name: Optional filter by row label.
        column_name: Optional filter by column label.
        report_for: Optional filter by report scope (e.g. ``"Entire Facility"``).

    Returns:
        List of TabularRow entries matching the filters.
    """
    query = (
        "SELECT ReportName, ReportForString, TableName, RowName, "
        "ColumnName, Units, Value "
        "FROM TabularDataWithStrings"
    )
    conditions: list[str] = []
    params: list[str] = []

    if report_name is not None:
        conditions.append("ReportName = ?")
        params.append(report_name)
    if table_name is not None:
        conditions.append("TableName = ?")
        params.append(table_name)
    if row_name is not None:
        conditions.append("RowName = ?")
        params.append(row_name)
    if column_name is not None:
        conditions.append("ColumnName = ?")
        params.append(column_name)
    if report_for is not None:
        conditions.append("ReportForString = ?")
        params.append(report_for)

    if conditions:
        query += " WHERE " + " AND ".join(conditions)

    cur = self._conn.cursor()
    cur.execute(query, params)

    return [
        TabularRow(
            report_name=row[0],
            report_for=row[1],
            table_name=row[2],
            row_name=row[3],
            column_name=row[4],
            units=row[5],
            value=row[6],
        )
        for row in cur.fetchall()
    ]

TimeSeriesResult

idfkit.simulation.parsers.sql.TimeSeriesResult dataclass

A single time series extracted from an EnergyPlus SQL database.

Attributes:

Name Type Description
variable_name str

The output variable name.

key_value str

The key value (e.g. zone or surface name).

units str

The variable units.

frequency str

The reporting frequency.

timestamps tuple[datetime, ...]

Timestamp for each data point.

values tuple[float, ...]

Numeric values for each data point.

Source code in src/idfkit/simulation/parsers/sql.py
@dataclass(frozen=True, slots=True)
class TimeSeriesResult:
    """A single time series extracted from an EnergyPlus SQL database.

    Attributes:
        variable_name: The output variable name.
        key_value: The key value (e.g. zone or surface name).
        units: The variable units.
        frequency: The reporting frequency.
        timestamps: Timestamp for each data point.
        values: Numeric values for each data point.
    """

    variable_name: str
    key_value: str
    units: str
    frequency: str
    timestamps: tuple[datetime, ...]
    values: tuple[float, ...]

    def to_dataframe(self) -> Any:
        """Convert to a pandas DataFrame.

        Requires pandas to be installed.

        Returns:
            A DataFrame with a ``timestamp`` index and a column for the values.

        Raises:
            ImportError: If pandas is not installed.
        """
        try:
            import pandas  # type: ignore[import-not-found]
        except ImportError:
            msg = "pandas is required for DataFrame conversion. Install it with: pip install idfkit[dataframes]"
            raise ImportError(msg) from None
        pd: Any = pandas
        return pd.DataFrame(  # type: ignore[no-any-return]
            {"timestamp": list(self.timestamps), self.variable_name: list(self.values)}
        ).set_index("timestamp")

    def plot(self, *, backend: Any = None, title: str | None = None) -> Any:
        """Plot this time series as a line chart.

        Auto-detects the plotting backend if not provided. Requires matplotlib
        or plotly to be installed.

        Args:
            backend: A PlotBackend instance. If not provided, auto-detects.
            title: Optional plot title. Defaults to ``"key_value: variable_name"``.

        Returns:
            A figure object from the backend.

        Raises:
            ImportError: If no plotting backend is available.
        """
        if backend is None:
            from ..plotting import get_default_backend

            backend = get_default_backend()
        plot_title = title or f"{self.key_value}: {self.variable_name}"
        return backend.line(
            list(self.timestamps),
            list(self.values),
            title=plot_title,
            xlabel="Time",
            ylabel=f"{self.variable_name} ({self.units})",
            label=self.key_value,
        )

variable_name instance-attribute

key_value instance-attribute

units instance-attribute

frequency instance-attribute

timestamps instance-attribute

values instance-attribute

to_dataframe()

Convert to a pandas DataFrame.

Requires pandas to be installed.

Returns:

Type Description
Any

A DataFrame with a timestamp index and a column for the values.

Raises:

Type Description
ImportError

If pandas is not installed.

Source code in src/idfkit/simulation/parsers/sql.py
def to_dataframe(self) -> Any:
    """Convert to a pandas DataFrame.

    Requires pandas to be installed.

    Returns:
        A DataFrame with a ``timestamp`` index and a column for the values.

    Raises:
        ImportError: If pandas is not installed.
    """
    try:
        import pandas  # type: ignore[import-not-found]
    except ImportError:
        msg = "pandas is required for DataFrame conversion. Install it with: pip install idfkit[dataframes]"
        raise ImportError(msg) from None
    pd: Any = pandas
    return pd.DataFrame(  # type: ignore[no-any-return]
        {"timestamp": list(self.timestamps), self.variable_name: list(self.values)}
    ).set_index("timestamp")

plot(*, backend=None, title=None)

Plot this time series as a line chart.

Auto-detects the plotting backend if not provided. Requires matplotlib or plotly to be installed.

Parameters:

Name Type Description Default
backend Any

A PlotBackend instance. If not provided, auto-detects.

None
title str | None

Optional plot title. Defaults to "key_value: variable_name".

None

Returns:

Type Description
Any

A figure object from the backend.

Raises:

Type Description
ImportError

If no plotting backend is available.

Source code in src/idfkit/simulation/parsers/sql.py
def plot(self, *, backend: Any = None, title: str | None = None) -> Any:
    """Plot this time series as a line chart.

    Auto-detects the plotting backend if not provided. Requires matplotlib
    or plotly to be installed.

    Args:
        backend: A PlotBackend instance. If not provided, auto-detects.
        title: Optional plot title. Defaults to ``"key_value: variable_name"``.

    Returns:
        A figure object from the backend.

    Raises:
        ImportError: If no plotting backend is available.
    """
    if backend is None:
        from ..plotting import get_default_backend

        backend = get_default_backend()
    plot_title = title or f"{self.key_value}: {self.variable_name}"
    return backend.line(
        list(self.timestamps),
        list(self.values),
        title=plot_title,
        xlabel="Time",
        ylabel=f"{self.variable_name} ({self.units})",
        label=self.key_value,
    )

TabularRow

idfkit.simulation.parsers.sql.TabularRow dataclass

A single row from an EnergyPlus tabular report.

Attributes:

Name Type Description
report_name str

The report name (e.g. "AnnualBuildingUtilityPerformanceSummary").

report_for str

The report scope (e.g. "Entire Facility").

table_name str

The table name within the report.

row_name str

The row label.

column_name str

The column label.

units str

The value units.

value str

The cell value as a string.

Source code in src/idfkit/simulation/parsers/sql.py
@dataclass(frozen=True, slots=True)
class TabularRow:
    """A single row from an EnergyPlus tabular report.

    Attributes:
        report_name: The report name (e.g. ``"AnnualBuildingUtilityPerformanceSummary"``).
        report_for: The report scope (e.g. ``"Entire Facility"``).
        table_name: The table name within the report.
        row_name: The row label.
        column_name: The column label.
        units: The value units.
        value: The cell value as a string.
    """

    report_name: str
    report_for: str
    table_name: str
    row_name: str
    column_name: str
    units: str
    value: str

report_name instance-attribute

report_for instance-attribute

table_name instance-attribute

row_name instance-attribute

column_name instance-attribute

units instance-attribute

value instance-attribute

VariableInfo

idfkit.simulation.parsers.sql.VariableInfo dataclass

Metadata about an available variable or meter in the SQL database.

This class represents both regular variables and meters because EnergyPlus stores them in a single ReportDataDictionary table, distinguished only by an IsMeter column. Use the is_meter flag to tell them apart.

For pre-simulation discovery from .rdd / .mdd files, see the separate OutputVariable and OutputMeter classes instead.

Attributes:

Name Type Description
name str

The variable name.

key_value str

The key value. Empty for meters.

frequency str

The reporting frequency.

units str

The variable units.

is_meter bool

Whether this is a meter (vs. a regular variable).

variable_type str

The variable type string (e.g. "Zone", "HVAC").

Source code in src/idfkit/simulation/parsers/sql.py
@dataclass(frozen=True, slots=True)
class VariableInfo:
    """Metadata about an available variable or meter in the SQL database.

    This class represents both regular variables and meters because EnergyPlus
    stores them in a single ``ReportDataDictionary`` table, distinguished only
    by an ``IsMeter`` column.  Use the [is_meter][idfkit.simulation.parsers.sql.VariableInfo.is_meter] flag to tell them
    apart.

    For pre-simulation discovery from ``.rdd`` / ``.mdd`` files, see the
    separate [OutputVariable][idfkit.simulation.parsers.rdd.OutputVariable] and
    [OutputMeter][idfkit.simulation.parsers.rdd.OutputMeter] classes instead.

    Attributes:
        name: The variable name.
        key_value: The key value.  Empty for meters.
        frequency: The reporting frequency.
        units: The variable units.
        is_meter: Whether this is a meter (vs. a regular variable).
        variable_type: The variable type string (e.g. ``"Zone"``, ``"HVAC"``).
    """

    name: str
    key_value: str
    frequency: str
    units: str
    is_meter: bool
    variable_type: str

name instance-attribute

key_value instance-attribute

frequency instance-attribute

units instance-attribute

is_meter instance-attribute

variable_type instance-attribute

EnvironmentInfo

idfkit.simulation.parsers.sql.EnvironmentInfo dataclass

Metadata about a simulation environment period.

Attributes:

Name Type Description
index int

The environment period index in the database.

name str

The environment name (e.g. "RUN PERIOD 1").

environment_type int

The type integer (1 = DesignDay, 2 = DesignRunPeriod, 3 = WeatherFileRunPeriod).

Source code in src/idfkit/simulation/parsers/sql.py
@dataclass(frozen=True, slots=True)
class EnvironmentInfo:
    """Metadata about a simulation environment period.

    Attributes:
        index: The environment period index in the database.
        name: The environment name (e.g. ``"RUN PERIOD 1"``).
        environment_type: The type integer (1 = DesignDay, 2 = DesignRunPeriod,
            3 = WeatherFileRunPeriod).
    """

    index: int
    name: str
    environment_type: int

index instance-attribute

name instance-attribute

environment_type instance-attribute