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
45 changes: 18 additions & 27 deletions ladybug/_datacollectionbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class BaseCollection(object):
__slots__ = ('_header', '_values', '_datetimes', '_validated_a_period')
_collection_type = None
_mutable = True
_enumeration = None

def __init__(self, header, values, datetimes):
"""Initialize base collection.
Expand Down Expand Up @@ -104,6 +103,16 @@ def validated_a_period(self):
"""
return self._validated_a_period

@property
def mutable_class(self):
"""Get the mutable class for this type of data collection."""
return self.__class__

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
return self.__class__

@property
def datetime_strings(self):
"""Get a list of datetime strings for this collection.
Expand Down Expand Up @@ -212,14 +221,12 @@ def is_in_data_type_range(self, raise_exception=True):

def to_mutable(self):
"""Get a mutable version of this collection."""
return self.duplicate()

return self.mutable_class(self.header, self.values, self.datetimes)

def to_immutable(self):
"""Get an immutable version of this collection."""
if self._enumeration is None:
self._get_mutable_enumeration()
col_obj = self._enumeration['immutable'][self._collection_type]
new_obj = col_obj(self.header, self.values, self.datetimes)
new_obj = self.immutable_class(self.header, self.values, self.datetimes)
new_obj._validated_a_period = self._validated_a_period
return new_obj

Expand Down Expand Up @@ -398,9 +405,7 @@ def filter_by_conditional_statement(self, statement):
A new Data Collection containing only the filtered data.
"""
_filt_values, _filt_datetimes = self._filter_by_statement(statement)
if self._enumeration is None:
self._get_mutable_enumeration()
col_obj = self._enumeration['mutable'][self._collection_type]
col_obj = self.mutable_class
try:
collection = col_obj(self.header.duplicate(), _filt_values, _filt_datetimes)
except AssertionError as e:
Expand All @@ -427,9 +432,7 @@ def filter_by_range(self, greater_than=float('-inf'), less_than=float('inf')):
A new Data Collection with filtered data.
"""
_filt_values, _filt_datetimes = self._filter_by_range(greater_than, less_than)
if self._enumeration is None:
self._get_mutable_enumeration()
col_obj = self._enumeration['mutable'][self._collection_type]
col_obj = self.mutable_class
try:
collection = col_obj(self.header.duplicate(), _filt_values, _filt_datetimes)
except AssertionError as e:
Expand All @@ -451,9 +454,7 @@ def filter_by_pattern(self, pattern):
A new Data Collection with filtered data.
"""
_filt_values, _filt_datetimes = self._filter_by_pattern(pattern)
if self._enumeration is None:
self._get_mutable_enumeration()
col_obj = self._enumeration['mutable'][self._collection_type]
col_obj = self.mutable_class
collection = col_obj(self.header.duplicate(), _filt_values, _filt_datetimes)
collection._validated_a_period = self._validated_a_period
return collection
Expand Down Expand Up @@ -509,12 +510,10 @@ def get_aligned_collection(self, value=0, data_type=None, unit=None, mutable=Non
if mutable is None:
collection = self.__class__(header, values, self.datetimes)
else:
if self._enumeration is None:
self._get_mutable_enumeration()
if not mutable:
col_obj = self._enumeration['immutable'][self._collection_type]
col_obj = self.immutable_class
else:
col_obj = self._enumeration['mutable'][self._collection_type]
col_obj = self.mutable_class
collection = col_obj(header, values, self.datetimes)
collection._validated_a_period = self._validated_a_period
return collection
Expand Down Expand Up @@ -1122,14 +1121,6 @@ def percentile_function(vals):
return self._percentile(vals, percentile)
return percentile_function

def _get_mutable_enumeration(self):
self._enumeration = {'mutable': {}, 'immutable': {}}
for clss in self._all_subclasses(BaseCollection):
if clss._mutable:
self._enumeration['mutable'][clss._collection_type] = clss
else:
self._enumeration['immutable'][clss._collection_type] = clss

def _all_subclasses(self, clss):
return set(clss.__subclasses__()).union(
[s for c in clss.__subclasses__() for s in self._all_subclasses(c)])
Expand Down
54 changes: 42 additions & 12 deletions ladybug/datacollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class HourlyDiscontinuousCollection(BaseCollection):
* validated_a_period
* values
"""

__slots__ = ()
_collection_type = 'HourlyDiscontinuous'

def __init__(self, header, values, datetimes):
Expand Down Expand Up @@ -141,6 +141,12 @@ def moys_dict(self):
moy_dict[dt.moy] = val
return moy_dict

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
from .datacollectionimmutable import HourlyDiscontinuousCollectionImmutable
return HourlyDiscontinuousCollectionImmutable

def filter_by_analysis_period(self, analysis_period):
"""Filter a Data Collection based on an analysis period.

Expand Down Expand Up @@ -595,7 +601,7 @@ class HourlyContinuousCollection(HourlyDiscontinuousCollection):
* validated_a_period
* values
"""

__slots__ = ()
_collection_type = 'HourlyContinuous'

def __init__(self, header, values):
Expand Down Expand Up @@ -644,6 +650,12 @@ def datetimes(self):
self._datetimes = self.header.analysis_period.datetimes
return self._datetimes

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
from .datacollectionimmutable import HourlyContinuousCollectionImmutable
return HourlyContinuousCollectionImmutable

def interpolate_holes(self):
"""All continuous collections do not have holes in the data set.

Expand Down Expand Up @@ -900,12 +912,13 @@ def group_by_month(self):
indx += interval
return hourly_data_by_month

def to_mutable(self):
"""Get an mutable version of this collection."""
return self.mutable_class(self.header, self.values)

def to_immutable(self):
"""Get an immutable version of this collection."""
if self._enumeration is None:
self._get_mutable_enumeration()
col_obj = self._enumeration['immutable'][self._collection_type]
return col_obj(self.header, self.values)
return self.immutable_class(self.header, self.values)

def get_aligned_collection(self, value=0, data_type=None, unit=None, mutable=None):
"""Return a Collection aligned with this one composed of one repeated value.
Expand Down Expand Up @@ -937,12 +950,10 @@ def get_aligned_collection(self, value=0, data_type=None, unit=None, mutable=Non
if mutable is None:
collection = self.__class__(header, values)
else:
if self._enumeration is None:
self._get_mutable_enumeration()
if not mutable:
col_obj = self._enumeration['immutable'][self._collection_type]
col_obj = self.immutable_class
else:
col_obj = self._enumeration['mutable'][self._collection_type]
col_obj = self.mutable_class
collection = col_obj(header, values)
return collection

Expand Down Expand Up @@ -1093,6 +1104,7 @@ class DailyCollection(BaseCollection):
* validated_a_period
* values
"""
__slots__ = ()
_collection_type = 'Daily'

def __init__(self, header, values, datetimes):
Expand All @@ -1118,6 +1130,12 @@ def datetime_strings(self):
lp_yr = self.header.analysis_period.is_leap_year
return [str(Date.from_doy(d, lp_yr)) for d in self._datetimes]

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
from .datacollectionimmutable import DailyCollectionImmutable
return DailyCollectionImmutable

def filter_by_analysis_period(self, analysis_period):
"""Filter the Data Collection based on an analysis period.

Expand Down Expand Up @@ -1341,7 +1359,7 @@ class MonthlyCollection(BaseCollection):
* validated_a_period
* values
"""

__slots__ = ()
_collection_type = 'Monthly'

def __init__(self, header, values, datetimes):
Expand All @@ -1366,6 +1384,12 @@ def datetime_strings(self):
"""
return [AnalysisPeriod.MONTHNAMES[int(d)] for d in self._datetimes]

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
from .datacollectionimmutable import MonthlyCollectionImmutable
return MonthlyCollectionImmutable

def filter_by_analysis_period(self, analysis_period):
"""Filter the Data Collection based on an analysis period.

Expand Down Expand Up @@ -1492,7 +1516,7 @@ class MonthlyPerHourCollection(BaseCollection):
* validated_a_period
* values
"""

__slots__ = ()
_collection_type = 'MonthlyPerHour'

def __init__(self, header, values, datetimes):
Expand Down Expand Up @@ -1520,6 +1544,12 @@ def datetime_strings(self):
for d in self._datetimes
]

@property
def immutable_class(self):
"""Get the immutable class for this type of data collection."""
from .datacollectionimmutable import MonthlyPerHourCollectionImmutable
return MonthlyPerHourCollectionImmutable

def filter_by_analysis_period(self, analysis_period):
"""Filter the Data Collection based on an analysis period.

Expand Down
31 changes: 31 additions & 0 deletions ladybug/datacollectionimmutable.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

class _ImmutableCollectionBase(object):
"""Base class for all immutable Data Collections."""
__slots__ = ()
_mutable = False

@property
Expand Down Expand Up @@ -62,6 +63,12 @@ def __setitem__(self, key, value):
class HourlyDiscontinuousCollectionImmutable(
_ImmutableCollectionBase, HourlyDiscontinuousCollection):
"""Immutable Discontinuous Data Collection at hourly or sub-hourly intervals."""
__slots__ = ()

@property
def mutable_class(self):
"""Get the immutable class for this type of data collection."""
return HourlyDiscontinuousCollection

def convert_to_culled_timestep(self, timestep=1):
"""This method is not available for immutable collections."""
Expand All @@ -77,6 +84,12 @@ def to_mutable(self):
class HourlyContinuousCollectionImmutable(
_ImmutableCollectionBase, HourlyContinuousCollection):
"""Immutable Continuous Data Collection at hourly or sub-hourly intervals."""
__slots__ = ()

@property
def mutable_class(self):
"""Get the immutable class for this type of data collection."""
return DailyCollection

def convert_to_culled_timestep(self, timestep=1):
"""This method is not available for immutable collections."""
Expand All @@ -96,6 +109,12 @@ def duplicate(self):
class DailyCollectionImmutable(
_ImmutableCollectionBase, DailyCollection):
"""Immutable Daily Data Collection."""
__slots__ = ()

@property
def mutable_class(self):
"""Get the immutable class for this type of data collection."""
return DailyCollection

def to_mutable(self):
"""Get a mutable version of this collection."""
Expand All @@ -107,6 +126,12 @@ def to_mutable(self):
class MonthlyCollectionImmutable(
_ImmutableCollectionBase, MonthlyCollection):
"""Immutable Monthly Data Collection."""
__slots__ = ()

@property
def mutable_class(self):
"""Get the immutable class for this type of data collection."""
return MonthlyCollection

def to_mutable(self):
"""Get a mutable version of this collection."""
Expand All @@ -118,6 +143,12 @@ def to_mutable(self):
class MonthlyPerHourCollectionImmutable(
_ImmutableCollectionBase, MonthlyPerHourCollection):
"""Immutable Monthly Per Hour Data Collection."""
__slots__ = ()

@property
def mutable_class(self):
"""Get the immutable class for this type of data collection."""
return MonthlyPerHourCollection

def to_mutable(self):
"""Get a mutable version of this collection."""
Expand Down
4 changes: 1 addition & 3 deletions ladybug/epw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1928,9 +1928,7 @@ def save(self, file_path):
Args:
file_path: Text for the full path to where the file will be written.
"""
file_data = self.to_file_string()
write_to_file(file_path, file_data, True)
return file_data
return self.write(file_path)

def ToString(self):
"""Overwrite .NET ToString."""
Expand Down
Loading