Source code for honeybee_energy.result.zsz
# coding=utf-8
"""Module for parsing EnergyPlus ZSZ csv result files into Ladybug DataCollections."""
from __future__ import division
from ladybug.futil import csv_to_matrix
from ladybug.datacollection import HourlyContinuousCollection
from ladybug.header import Header
from ladybug.analysisperiod import AnalysisPeriod
from ladybug.dt import Date
from ladybug.datatype.power import Power
from ladybug.datatype.massflowrate import MassFlowRate
import os
from datetime import datetime
[docs]
class ZSZ(object):
"""Object for parsing EnergyPlus Zone Sizing (ZSZ) csv result files.
Args:
file_path: Full path to a ZSZ csv file that was generated by EnergyPlus.
cooling_date: A ladybug Date object for the cooling design day. This is needed
as the ZSZ file contains no information about the dates of the loads.
heating_date: A ladybug Date object for the heating design day. This is needed
as the ZSZ file contains no information about the dates of the loads.
Properties:
* file_path
* cooling_date
* heating_date
* timestep
* cooling_load_data
* heating_load_data
* cooling_flow_data
* heating_flow_data
"""
# a list if keywords to identify design day names from room names in headers
DES_DAY_KEYWORDS = (' CLG ', ' HTG ', ' DESIGN DAY ')
def __init__(self, file_path, cooling_date=Date(1, 1), heating_date=Date(1, 1)):
"""Initialize ZSZ"""
# check that the file exists
assert os.path.isfile(file_path), 'No file was found at {}'.format(file_path)
assert file_path.endswith('.csv'), \
'{} is not an CSV file ending in .csv.'.format(file_path)
self._file_path = file_path
# parse the data in the file
data_mtx = csv_to_matrix(file_path)
# extract the header and the peak values
headers = data_mtx[0][:] # copy the list
del headers[0]
peak = data_mtx[-3][:] # copy the list
del peak[0]
del data_mtx[0]
for i in range(3):
del data_mtx[-1]
self._headers = headers
self._peak = peak
# process the timestep of the data
data_mtx = list(zip(*data_mtx))
time1 = datetime.strptime(data_mtx[0][0], '%H:%M:%S')
time2 = datetime.strptime(data_mtx[0][1], '%H:%M:%S')
t_delta = time2 - time1
self._timestep = int(3600 / t_delta.seconds)
self._cooling_date = cooling_date
self._heating_date = heating_date
self._cool_a_period = AnalysisPeriod(
cooling_date.month, cooling_date.day, 0,
cooling_date.month, cooling_date.day, 23, timestep=self._timestep)
self._heat_a_period = AnalysisPeriod(
heating_date.month, heating_date.day, 0,
heating_date.month, heating_date.day, 23, timestep=self._timestep)
# process the body of the data
del data_mtx[0]
self._data = data_mtx
# properties to be computed upon request
self._cooling_load_data = None
self._heating_load_data = None
self._cooling_flow_data = None
self._heating_flow_data = None
@property
def file_path(self):
"""Get the path to the .rdd file."""
return self._file_path
@property
def cooling_date(self):
"""Get the date object assigned to the cooling design day."""
return self._cooling_date
@property
def heating_date(self):
"""Get the date object assigned to the heating design day."""
return self._heating_date
@property
def timestep(self):
"""Get the timestep of the data in the file."""
return self._timestep
@property
def cooling_load_data(self):
"""Get a list of HourlyContinuousCollections for zone cooling load.
There will be one data collection per conditioned zone in the model. Data
collections are at the timestep of this object and values are in Watts.
"""
if self._cooling_load_data is None:
self._cooling_load_data = self._process_collections(
'Summer Design Day Sensible Cooling Load', 'Des Sens Cool Load [W]', 'W')
return self._cooling_load_data
@property
def heating_load_data(self):
"""Get a list of HourlyContinuousCollections for zone heating load.
There will be one data collection per conditioned zone in the model. Data
collections are at the timestep of this object and values are in Watts.
"""
if self._heating_load_data is None:
self._heating_load_data = self._process_collections(
'Winter Design Day Heating Load', 'Des Heat Load [W]', 'W')
return self._heating_load_data
@property
def cooling_flow_data(self):
"""Get a list of HourlyContinuousCollections for zone cooling mass flow.
There will be one data collection per conditioned zone in the model. Data
collections are at the timestep of this object and values are in m3/s.
"""
if self._cooling_flow_data is None:
self._cooling_flow_data = self._process_collections(
'Summer Design Day Cooling Mass Flow',
'Des Cool Mass Flow [kg/s]', 'kg/s')
return self._cooling_flow_data
@property
def heating_flow_data(self):
"""Get a list of HourlyContinuousCollections for zone heating mass flow.
There will be one data collection per conditioned zone in the model. Data
collections are at the timestep of this object and values are in m3/s.
"""
if self._heating_flow_data is None:
self._heating_flow_data = self._process_collections(
'Winter Design Day Heating Flow', 'Des Heat Mass Flow [kg/s]', 'kg/s')
return self._heating_flow_data
def _process_collections(self, description, data_type_text, unit):
"""Convert the raw data in the hidden _data property to data collections."""
data_type = Power() if unit == 'W' else MassFlowRate()
a_per = self._cool_a_period if 'Summer' in description else self._heat_a_period
collections = []
for i, col_head in enumerate(self._headers):
if data_type_text in col_head:
# try to differentiate the Zone name from the design day name
c_head, zone_names, end_found = col_head.split(':')[:-1], [], False
for name in c_head:
for kwrd in self.DES_DAY_KEYWORDS:
if kwrd in name:
end_found = True
break
else:
zone_names.append(name)
if end_found:
break
if len(zone_names) == len(c_head): # we did not find it
zone_name = c_head[0]
else:
zone_name = ':'.join(zone_names)
# create the header
metadata = {'type': description, 'Zone': zone_name}
head = Header(data_type, unit, a_per, metadata)
collections.append(HourlyContinuousCollection(
head, [float(val) for val in self._data[i]]))
return collections
[docs]
def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()
def __repr__(self):
return 'Energy ZSZ Result: {}'.format(self.file_path)