diff --git a/ladybug/datatype/percentage.py b/ladybug/datatype/fraction.py similarity index 57% rename from ladybug/datatype/percentage.py rename to ladybug/datatype/fraction.py index 11c7e28e..c6beea93 100644 --- a/ladybug/datatype/percentage.py +++ b/ladybug/datatype/fraction.py @@ -1,44 +1,44 @@ # coding=utf-8 -"""Percentage data type.""" +"""Fraction data type.""" from __future__ import division from .base import DataTypeBase -class Percentage(DataTypeBase): - """Percentage""" - _units = ('%', 'fraction', 'tenths', 'thousandths', 'okta') - _si_units = ('%', 'fraction', 'tenths', 'thousandths', 'okta') - _ip_units = ('%', 'fraction', 'tenths', 'thousandths', 'okta') +class Fraction(DataTypeBase): + """Fraction""" + _units = ('fraction', '%', 'tenths', 'thousandths', 'okta') + _si_units = ('fraction', '%', 'tenths', 'thousandths', 'okta') + _ip_units = ('fraction', '%', 'tenths', 'thousandths', 'okta') _abbreviation = 'Pct' - def _pct_to_fraction(self, value): - return value / 100. - - def _pct_to_tenths(self, value): - return value / 10. + def _fraction_to_pct(self, value): + return value * 100. - def _pct_to_thousandths(self, value): + def _fraction_to_tenths(self, value): return value * 10. - def _pct_to_okta(self, value): - return value / 12.5 + def _fraction_to_thousandths(self, value): + return value * 1000. - def _fraction_to_pct(self, value): - return value * 100. + def _fraction_to_okta(self, value): + return value * 12.5 - def _tenths_to_pct(self, value): - return value * 10. + def _pct_to_fraction(self, value): + return value / 100. - def _thousandths_to_pct(self, value): + def _tenths_to_fraction(self, value): return value / 10. - def _okta_to_pct(self, value): - return value * 12.5 + def _thousandths_to_fraction(self, value): + return value / 1000. + + def _okta_to_fraction(self, value): + return value / 12.5 def to_unit(self, values, unit, from_unit): """Return values converted to the unit given the input from_unit.""" - return self._to_unit_base('%', values, unit, from_unit) + return self._to_unit_base('fraction', values, unit, from_unit) def to_ip(self, values, from_unit): """Return values in IP and the units to which the values have been converted.""" @@ -49,72 +49,72 @@ def to_si(self, values, from_unit): return values, from_unit @property - def isPercentage(self): + def isFraction(self): """Return True.""" return True -class PercentagePeopleDissatisfied(Percentage): +class PercentagePeopleDissatisfied(Fraction): _min = 0 - _max = 100 + _max = 1 _abbreviation = 'PPD' -class RelativeHumidity(Percentage): +class RelativeHumidity(Fraction): _min = 0 _abbreviation = 'RH' _min_epw = 0 - _max_epw = 110 + _max_epw = 1.1 _missing_epw = 999 -class HumidityRatio(Percentage): +class HumidityRatio(Fraction): _min = 0 - _max = 100 + _max = 1 _abbreviation = 'HR' -class TotalSkyCover(Percentage): +class TotalSkyCover(Fraction): # (used if Horizontal IR Intensity missing) _min = 0 - _max = 100 + _max = 1 _abbreviation = 'CC' _min_epw = 0 - _max_epw = 100 + _max_epw = 1 _missing_epw = 99 -class OpaqueSkyCover(Percentage): +class OpaqueSkyCover(Fraction): # (used if Horizontal IR Intensity missing) _min = 0 - _max = 100 + _max = 1 _abbreviation = 'OSC' _min_epw = 0 - _max_epw = 100 + _max_epw = 1 _missing_epw = 99 -class AerosolOpticalDepth(Percentage): +class AerosolOpticalDepth(Fraction): _min = 0 - _max = 100 + _max = 1 _abbreviation = 'AOD' _min_epw = 0 - _max_epw = 100 + _max_epw = 1 _missing_epw = 0.999 -class Albedo(Percentage): +class Albedo(Fraction): _min = 0 - _max = 100 + _max = 1 _abbreviation = 'a' _min_epw = 0 - _max_epw = 100 + _max_epw = 1 _missing_epw = 0.999 -class LiquidPrecipitationQuantity(Percentage): +class LiquidPrecipitationQuantity(Fraction): _min = 0 _abbreviation = 'LPQ' _min_epw = 0 - _max_epw = 100 + _max_epw = 1 _missing_epw = 99 diff --git a/ladybug/datatype/temperaturetime.py b/ladybug/datatype/temperaturetime.py new file mode 100644 index 00000000..6f85934b --- /dev/null +++ b/ladybug/datatype/temperaturetime.py @@ -0,0 +1,66 @@ +# coding=utf-8 +"""Temperature-Time data type.""" +from __future__ import division + +from .base import DataTypeBase + + +class TemperatureTime(DataTypeBase): + """Temperature-Time""" + _units = ('degC-days', 'degF-days', 'degC-hours', 'degF-hours') + _si_units = ('degC-days', 'degC-hours') + _ip_units = ('degF-days', 'degF-hours') + _abbreviation = 'degTime' + + def _degCdays_to_degFdays(self, value): + return value * 9. / 5. + + def _degCdays_to_degChours(self, value): + return value * 24. + + def _degCdays_to_degFhours(self, value): + return value * 24. * 9. / 5. + + def _degFdays_to_degCdays(self, value): + return value * 5. / 9. + + def _degChours_to_degCdays(self, value): + return value / 24. + + def _degFhours_to_degCdays(self, value): + return (value / 24.) * 5. / 9. + + def to_unit(self, values, unit, from_unit): + """Return values converted to the unit given the input from_unit.""" + return self._to_unit_base('degC-days', values, unit, from_unit) + + def to_ip(self, values, from_unit): + """Return values in IP and the units to which the values have been converted.""" + if from_unit in self._ip_units: + return values, from_unit + elif from_unit == 'degC-hours': + return self.to_unit(values, 'degF-hours', from_unit), 'degF-hours' + else: + return self.to_unit(values, 'degF-days', from_unit), 'degF-days' + + def to_si(self, values, from_unit): + """Return values in SI and the units to which the values have been converted.""" + if from_unit in self._si_units: + return values, from_unit + elif from_unit == 'degF-hours': + return self.to_unit(values, 'degC-hours', from_unit), 'degC-hours' + else: + return self.to_unit(values, 'degC-days', from_unit), 'degC-days' + + @property + def isTemperatureTime(self): + """Return True.""" + return True + + +class CoolingDegreeTime(TemperatureTime): + _abbreviation = 'coolTime' + + +class HeatingDegreeTime(TemperatureTime): + _abbreviation = 'heatTime' diff --git a/ladybug/designday.py b/ladybug/designday.py index 1086460c..dfd7f9b3 100644 --- a/ladybug/designday.py +++ b/ladybug/designday.py @@ -10,7 +10,7 @@ from .sunpath import Sunpath from .datatype import angle, energyflux, energyintensity, \ - percentage, pressure, speed, temperature + fraction, pressure, speed, temperature from .skymodel import ashrae_revised_clear_sky, \ ashrae_clear_sky, calc_horizontal_infrared @@ -663,7 +663,7 @@ def hourly_relative_humidity(self): rh_data = [rel_humid_from_db_dpt(x, y) for x, y in zip( self._dry_bulb_condition.hourly_values, dpt_data)] return self._get_daily_data_collections( - percentage.RelativeHumidity(), '%', rh_data) + fraction.RelativeHumidity(), '%', rh_data) @property def hourly_barometric_pressure(self): @@ -705,7 +705,7 @@ def hourly_solar_radiation(self): def hourly_sky_cover(self): """A data collection containing hourly sky cover values in tenths.""" return self._get_daily_data_collections( - percentage.TotalSkyCover(), 'tenths', self._sky_condition.hourly_sky_cover) + fraction.TotalSkyCover(), 'tenths', self._sky_condition.hourly_sky_cover) @property def hourly_horizontal_infrared(self): diff --git a/ladybug/epw.py b/ladybug/epw.py index 368b555d..f25b8dc7 100644 --- a/ladybug/epw.py +++ b/ladybug/epw.py @@ -8,7 +8,7 @@ from .header import Header from .analysisperiod import AnalysisPeriod from .datatype import angle, distance, energyflux, energyintensity, generic, \ - illuminance, luminance, percentage, pressure, speed, temperature + illuminance, luminance, fraction, pressure, speed, temperature from .skymodel import calc_sky_temperature from .futil import write_to_file @@ -1433,7 +1433,7 @@ class EPWFields(object): 'unit': 'C' }, - 8: {'name': percentage.RelativeHumidity(), + 8: {'name': fraction.RelativeHumidity(), 'type': int, 'unit': '%' }, @@ -1503,12 +1503,12 @@ class EPWFields(object): 'unit': 'm/s' }, - 22: {'name': percentage.TotalSkyCover(), # used if Horizontal IR is missing + 22: {'name': fraction.TotalSkyCover(), # used if Horizontal IR is missing 'type': int, 'unit': 'tenths' }, - 23: {'name': percentage.OpaqueSkyCover(), # used if Horizontal IR is missing + 23: {'name': fraction.OpaqueSkyCover(), # used if Horizontal IR is missing 'type': int, 'unit': 'tenths' }, @@ -1540,7 +1540,7 @@ class EPWFields(object): 'unit': 'mm' }, - 29: {'name': percentage.AerosolOpticalDepth(), + 29: {'name': fraction.AerosolOpticalDepth(), 'type': float, 'unit': 'fraction' }, @@ -1556,7 +1556,7 @@ class EPWFields(object): 'unit': 'day' }, - 32: {'name': percentage.Albedo(), + 32: {'name': fraction.Albedo(), 'type': float, 'unit': 'fraction' }, @@ -1566,7 +1566,7 @@ class EPWFields(object): 'unit': 'mm' }, - 34: {'name': percentage.LiquidPrecipitationQuantity(), + 34: {'name': fraction.LiquidPrecipitationQuantity(), 'type': float, 'unit': 'fraction' } diff --git a/tests/datacollection_test.py b/tests/datacollection_test.py index 6af419d9..52f059c1 100644 --- a/tests/datacollection_test.py +++ b/tests/datacollection_test.py @@ -10,7 +10,7 @@ from ladybug.dt import DateTime from ladybug.datatype.generic import GenericType from ladybug.datatype.temperature import Temperature -from ladybug.datatype.percentage import RelativeHumidity, HumidityRatio +from ladybug.datatype.fraction import RelativeHumidity, HumidityRatio from ladybug.epw import EPW from ladybug.psychrometrics import humid_ratio_from_db_rh diff --git a/tests/datatype_test.py b/tests/datatype_test.py index 602d5a48..d3a9c604 100644 --- a/tests/datatype_test.py +++ b/tests/datatype_test.py @@ -4,8 +4,8 @@ from ladybug import datatype from ladybug.datatype import base from ladybug.datatype import angle, area, distance, energy, energyflux, \ - energyintensity, generic, illuminance, luminance, mass, massflowrate, \ - percentage, power, pressure, rvalue, speed, temperature, temperaturedelta, \ + energyintensity, fraction, generic, illuminance, luminance, mass, massflowrate, \ + power, pressure, rvalue, speed, temperature, temperaturedelta, temperaturetime, \ thermalcondition, specificenergy, uvalue, volume, volumeflowrate import unittest @@ -94,9 +94,27 @@ def test_temperaturedelta(self): assert temp_type.to_unit([1], 'C', 'F')[0] == pytest.approx(0.5555, rel=1e-1) assert temp_type.to_unit([1], 'C', 'K')[0] == pytest.approx(1, rel=1e-1) - def test_percentage(self): - """Test Percentage type.""" - pct_type = percentage.Percentage() + def test_temperaturetime(self): + """Test TemperatureTime type.""" + temp_type = temperaturetime.TemperatureTime() + for unit in temp_type.units: + assert temp_type.to_unit([1], unit, unit)[0] == pytest.approx(1, rel=1e-5) + ip_vals, ip_u = temp_type.to_ip([1], unit) + assert len(ip_vals) == 1 + si_vals, si_u = temp_type.to_si([1], unit) + assert len(si_vals) == 1 + for other_unit in temp_type.units: + assert len(temp_type.to_unit([1], other_unit, unit)) == 1 + assert temp_type.to_unit([1], 'degF-days', 'degC-days')[0] == pytest.approx(1.8, rel=1e-1) + assert temp_type.to_unit([1], 'degC-hours', 'degC-days')[0] == pytest.approx(24, rel=1e-3) + assert temp_type.to_unit([1], 'degF-hours', 'degC-days')[0] == pytest.approx(43.2, rel=1e-1) + assert temp_type.to_unit([1], 'degC-days', 'degF-days')[0] == pytest.approx(0.5555, rel=1e-1) + assert temp_type.to_unit([1], 'degC-days', 'degC-hours')[0] == pytest.approx(1 / 24, rel=1e-1) + assert temp_type.to_unit([1], 'degC-days', 'degF-hours')[0] == pytest.approx(0.023148, rel=1e-1) + + def test_fraction(self): + """Test Fraction type.""" + pct_type = fraction.Fraction() for unit in pct_type.units: assert pct_type.to_unit([1], unit, unit)[0] == pytest.approx(1, rel=1e-5) ip_vals, ip_u = pct_type.to_ip([1], unit)