Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion db_eplusout_reader/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,5 +3,18 @@
from db_eplusout_reader.db_esofile import DBEsoFile, DBEsoFileCollection
from db_eplusout_reader.get_results import get_results
from db_eplusout_reader.processing.esofile_reader import Variable
from db_eplusout_reader.sql_reader import (
get_all_variables,
get_tables,
get_variables,
)

__all__ = ["DBEsoFile", "DBEsoFileCollection", "get_results", "Variable"]
__all__ = [
"DBEsoFile",
"DBEsoFileCollection",
"get_results",
"Variable",
"get_tables",
"get_variables",
"get_all_variables",
]
96 changes: 93 additions & 3 deletions db_eplusout_reader/sql_reader.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -225,6 +225,98 @@ def get_timestamps_from_sql(path, frequency, start_date=None, end_date=None):
return timestamps


def connect(path):
"""Open a connection to an existing .sql file."""
if not os.path.exists(path):
raise IOError("Cannot read results, file '{}' does not exist.".format(path))
return sqlite3.connect(path)


def get_tables(path):
"""
Return the reporting frequencies (tables) available in the .sql file.

Parameters
----------
path : str
A path to EnergyPlus .sql file output.

Returns
-------
list of str
Available frequencies as {TS, H, D, M, A, RP} constants, ordered
from the most to the least granular.

"""
conn = connect(path)
try:
rows = conn.execute(
"SELECT DISTINCT ReportingFrequency FROM ReportDataDictionary"
).fetchall()
finally:
conn.close()
order = {TS: 0, H: 1, D: 2, M: 3, A: 4, RP: 5}
tables = []
for (sql_frequency,) in rows:
frequency = to_eso_frequency(sql_frequency)
# 'Zone Timestep' and 'HVAC System Timestep' both map to TS
if frequency not in tables:
tables.append(frequency)
return sorted(tables, key=lambda f: order[f])


def get_variables(path, frequency):
"""
Return the variables available for the given frequency (table).

Parameters
----------
path : str
A path to EnergyPlus .sql file output.
frequency : str
An output interval, one of {TS, H, D, M, A, RP} constants.

Returns
-------
list of Variable
Available variables for the frequency, sorted.

"""
conn = connect(path)
try:
sql_frequency = to_sql_frequency(frequency)
rows = conn.execute(
"SELECT ReportDataDictionaryIndex, ReportingFrequency, KeyValue, Name, Units"
" FROM ReportDataDictionary WHERE ReportingFrequency = ?",
(sql_frequency,),
)
ids_dict = get_unsorted_sub_dict(rows)
finally:
conn.close()
return list(sort_by_value(ids_dict).values())


def get_all_variables(path):
"""
Return an overview of every available variable grouped by frequency.

Parameters
----------
path : str
A path to EnergyPlus .sql file output.

Returns
-------
OrderedDict of {str : list of Variable}
Mapping of frequency (table) to its available variables.

"""
overview = OrderedDict()
for frequency in get_tables(path):
overview[frequency] = get_variables(path, frequency)
return overview


def get_results_from_sql(
path, variables, frequency, alike=False, start_date=None, end_date=None
):
Expand DownExpand Up@@ -252,9 +344,7 @@ def get_results_from_sql(
ResultsDictionary : Dict of {Variable, list of float}

"""
if not os.path.exists(path):
raise IOError("Cannot read results, file '{}' does not exist.".format(path))
conn = sqlite3.connect(path)
conn = connect(path)
variables = [variables] if isinstance(variables, Variable) else variables
sql_frequency = to_sql_frequency(frequency)
ids_dict = get_ids_dict(conn, variables, sql_frequency, alike)
Expand Down
42 changes: 41 additions & 1 deletion tests/test_sql_results.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,13 @@

import pytest

from db_eplusout_reader import Variable, get_results
from db_eplusout_reader import (
Variable,
get_all_variables,
get_results,
get_tables,
get_variables,
)
from db_eplusout_reader.constants import RP, TS, A, D, H, M
from db_eplusout_reader.results_dict import ResultsHandler
from db_eplusout_reader.sql_reader import (
Expand DownExpand Up@@ -114,6 +120,40 @@ def test_invalid_file_path(self, test_files_dir):
assert not os.path.exists(invalid_path)


class TestListVariables:
def test_get_tables(self, any_sql_path):
tables = get_tables(any_sql_path)
assert len(tables) > 0
# frequencies are returned as eso constants and de-duplicated
assert len(tables) == len(set(tables))
assert {H, D}.issubset(set(tables))

def test_get_variables_for_frequency(self, sql_path):
variables = get_variables(sql_path, H)
assert len(variables) > 0
assert all(isinstance(v, Variable) for v in variables)
assert _DRYBULB in variables
# sorted and unique
assert variables == sorted(variables)

def test_listed_variable_is_retrievable(self, sql_path):
# a listed (non-meter) variable can be fetched via get_results
variables = get_variables(sql_path, H)
assert _DRYBULB in variables
results = get_results(sql_path, _DRYBULB, frequency=H)
assert results.first_variable == _DRYBULB

def test_get_all_variables(self, sql_path):
overview = get_all_variables(sql_path)
assert set(overview.keys()) == set(get_tables(sql_path))
for frequency, variables in overview.items():
assert variables == get_variables(sql_path, frequency)

def test_get_tables_missing_file(self, test_files_dir):
with pytest.raises(IOError):
get_tables(os.path.join(test_files_dir, "nope.sql"))


class TestSqlInternals:
def test_to_eso_frequency_all(self):
assert to_eso_frequency("Zone Timestep") == TS
Expand Down
Loading