Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mtx): Add binary option to command #374

Merged
merged 4 commits into from
Aug 20, 2024
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
21 changes: 17 additions & 4 deletions ladybug_comfort/cli/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,14 @@ def utci(result_sql, enclosure_info, epw_file,
@click.option('--log-file', '-log', help='Optional log file to output the paths to the '
'generated CSV files. By default this will be printed out to stdout',
type=click.File('w'), default='-', show_default=True)
@click.option('--plain-text/--binary', ' /-b', help='Flag to note whether the '
'output should be formatted as a plain text CSV or whether it '
'should be formatted as a binary numpy array.',
default=True, show_default=True)
def irradiance_contrib(
result_sql, direct_specular, indirect_specular, ref_specular,
indirect_diffuse, ref_diffuse, sun_up_hours, aperture_id, folder, log_file
indirect_diffuse, ref_diffuse, sun_up_hours, aperture_id, folder, log_file,
plain_text
):
"""Get CSV files with irradiance contributions from dynamic windows.

Expand Down Expand Up @@ -466,9 +471,17 @@ def irradiance_contrib(
ref_file = os.path.join(out_folder, 'reflected.ill')

# write the irradiance matrices into CSV files
_data_to_ill(direct_mtx, direct_file)
_data_to_ill(indirect_mtx, indirect_file)
_data_to_ill(ref_mtx, ref_file)
if plain_text:
_data_to_ill(direct_mtx, direct_file)
_data_to_ill(indirect_mtx, indirect_file)
_data_to_ill(ref_mtx, ref_file)
else:
with open(direct_file, 'wb') as fp:
np.save(fp, set_smallest_dtype(np.array(direct_mtx)))
with open(indirect_file, 'wb') as fp:
np.save(fp, set_smallest_dtype(np.array(indirect_mtx)))
with open(ref_file, 'wb') as fp:
np.save(fp, set_smallest_dtype(np.array(ref_mtx)))
log_file.write(json.dumps([direct_file, indirect_file, ref_file]))
except Exception as e:
_logger.exception('Failed to run Shortwave MRT Delta map.\n{}'.format(e))
Expand Down
43 changes: 26 additions & 17 deletions ladybug_comfort/cli/mtx.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ def mtx():
@click.option('--log-file', '-log', help='Optional log file to output the paths to the '
'generated CSV files. By default this will be printed out to stdout',
type=click.File('w'), default='-', show_default=True)
@click.option('--plain-text/--binary', ' /-b', help='Flag to note whether the '
'output should be formatted as a plain text CSV or whether it '
'should be formatted as a binary numpy array.',
default=True, show_default=True)
def pmv_mtx(
temperature_mtx, rel_humidity_mtx, rad_temperature_mtx, rad_delta_mtx,
air_speed_mtx, air_speed_json, air_speed,
met_rate, clo_value, write_op_map, comfort_par, folder, log_file
met_rate, clo_value, write_op_map, comfort_par, folder, log_file, plain_text
):
"""Get CSV files with matrices of PMV comfort from matrices of PMV inputs.

Expand All @@ -102,20 +106,19 @@ def pmv_mtx(
"""
try:
# load up the matrices of values
air_temp = csv_to_num_matrix(temperature_mtx)
rel_h = csv_to_num_matrix(rel_humidity_mtx)
rad_temp = csv_to_num_matrix(rad_temperature_mtx) \
air_temp = load_matrix(temperature_mtx)
rel_h = load_matrix(rel_humidity_mtx)
rad_temp = load_matrix(rad_temperature_mtx) \
if rad_temperature_mtx is not None else air_temp
if rad_delta_mtx is not None and not os.path.getsize(rad_delta_mtx) == 0:
d_rad_temp = csv_to_num_matrix(rad_delta_mtx)
rad_temp = tuple(tuple(t + dt for t, dt in zip(t_pt, dt_pt))
for t_pt, dt_pt in zip(rad_temp, d_rad_temp))
d_rad_temp = load_matrix(rad_delta_mtx)
rad_temp = rad_temp + d_rad_temp
mtx_len = len(air_temp[0])

# process any of the other inputs for air speed
a_speed = None
if air_speed_mtx is not None and os.path.isfile(air_speed_mtx):
a_speed = csv_to_num_matrix(air_speed_mtx)
a_speed = load_matrix(air_speed_mtx).tolist()
if a_speed is None and air_speed_json is not None \
and os.path.isfile(air_speed_json):
with open(air_speed_json) as json_file:
Expand Down Expand Up @@ -166,7 +169,8 @@ def pmv_mtx(
# write out the final results to CSV files
if folder is None:
folder = os.path.join(os.path.dirname(temperature_mtx), 'thermal_mtx')
result_file_dict = thermal_map_csv(folder, temper, cond, cond_intensity)
result_file_dict = thermal_map_csv(
folder, temper, cond, cond_intensity, plain_text=plain_text)
log_file.write(json.dumps(result_file_dict))
except Exception as e:
_logger.exception('Failed to run PMV matrix.\n{}'.format(e))
Expand Down Expand Up @@ -215,9 +219,14 @@ def pmv_mtx(
@click.option('--log-file', '-log', help='Optional log file to output the paths to the '
'generated CSV files. By default this will be printed out to stdout',
type=click.File('w'), default='-', show_default=True)
@click.option('--plain-text/--binary', ' /-b', help='Flag to note whether the '
'output should be formatted as a plain text CSV or whether it '
'should be formatted as a binary numpy array.',
default=True, show_default=True)
def adaptive_mtx(
temperature_mtx, prevail_temp, rad_temperature_mtx, rad_delta_mtx,
air_speed_mtx, air_speed_json, air_speed, comfort_par, folder, log_file
air_speed_mtx, air_speed_json, air_speed, comfort_par, folder, log_file,
plain_text
):
"""Get CSV files with matrices of Adaptive comfort from matrices of Adaptive inputs.

Expand All @@ -230,20 +239,19 @@ def adaptive_mtx(
"""
try:
# load up the matrices of values
air_temp = csv_to_num_matrix(temperature_mtx)
air_temp = load_matrix(temperature_mtx)
prevail_temp = csv_to_num_matrix(prevail_temp)[0]
rad_temp = csv_to_num_matrix(rad_temperature_mtx) \
rad_temp = load_matrix(rad_temperature_mtx) \
if rad_temperature_mtx is not None else air_temp
if rad_delta_mtx is not None and not os.path.getsize(rad_delta_mtx) == 0:
d_rad_temp = csv_to_num_matrix(rad_delta_mtx)
rad_temp = tuple(tuple(t + dt for t, dt in zip(t_pt, dt_pt))
for t_pt, dt_pt in zip(rad_temp, d_rad_temp))
d_rad_temp = load_matrix(rad_delta_mtx)
rad_temp = rad_temp + d_rad_temp
mtx_len = len(air_temp[0])

# process any of the other inputs for air speed
a_speed = None
if air_speed_mtx is not None and os.path.isfile(air_speed_mtx):
a_speed = csv_to_num_matrix(air_speed_mtx)
a_speed = load_matrix(air_speed_mtx).tolist()
if a_speed is None and air_speed_json is not None \
and os.path.isfile(air_speed_json):
with open(air_speed_json) as json_file:
Expand Down Expand Up @@ -290,7 +298,8 @@ def adaptive_mtx(
# write out the final results to CSV files
if folder is None:
folder = os.path.join(os.path.dirname(temperature_mtx), 'thermal_mtx')
result_file_dict = thermal_map_csv(folder, temper, cond, cond_intensity)
result_file_dict = thermal_map_csv(
folder, temper, cond, cond_intensity, plain_text=plain_text)
log_file.write(json.dumps(result_file_dict))
except Exception as e:
_logger.exception('Failed to run PMV matrix.\n{}'.format(e))
Expand Down
39 changes: 32 additions & 7 deletions ladybug_comfort/map/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def binary_mtx_dimension(filepath):
filepath: Full path to Radiance file.

Returns:
nrows, ncols, ncomp, line_count
nrows, ncols, ncomp, line_count, fmt
"""
try:
inf = open(filepath, 'rb', encoding='utf-8')
Expand All @@ -39,6 +39,7 @@ def binary_mtx_dimension(filepath):
if line[:6] == 'NCOMP=':
ncomp = int(line.split('=')[-1])
if line[:7] == 'FORMAT=':
fmt = line.split('=')[-1]
break

if not nrows or not ncols:
Expand All @@ -48,34 +49,58 @@ def binary_mtx_dimension(filepath):
f'elements.'
)
raise ValueError(error_message)
return nrows, ncols, ncomp, len(header_lines) + 1
return nrows, ncols, ncomp, len(header_lines) + 1, fmt
finally:
inf.close()


def binary_to_array(binary_file, nrows=None, ncols=None, ncomp=None, line_count=0):
def binary_to_array(
binary_file, nrows=None, ncols=None, ncomp=None, fmt=None,
line_count=0):
"""Read a Radiance binary file as a NumPy array.

Args:
binary_file: Path to binary Radiance file.
nrows: Number of rows in the Radiance file.
ncols: Number of columns in the Radiance file.
ncomp: Number of components of each element in the Radiance file.
fmt: Format of the Radiance file. Can be either "ascii", "float", or "double.
line_count: Number of lines to skip in the input file. Usually used to
skip the header.

Returns:
A NumPy array.
"""
with open(binary_file, 'rb') as file:
# check if file is NumPy file
numpy_header = file.read(6)
if numpy_header.startswith(b'\x93NUMPY'):
file.seek(0)
array = np.load(file)
return array
file.seek(0)
# check if file has Radiance header, if not it is a text file
radiance_header = file.read(10).decode('utf-8')
if radiance_header != '#?RADIANCE':
file.seek(0)
array = np.genfromtxt(file, dtype=np.float32)
return array

if (nrows or ncols or ncomp or fmt) is None:
# get nrows, ncols and header line count
nrows, ncols, ncomp, line_count, fmt = binary_mtx_dimension(binary_file)
with open(binary_file, 'rb') as reader:
if (nrows or ncols or ncomp) is None:
# get nrows, ncols and header line count
nrows, ncols, ncomp, line_count = binary_mtx_dimension(binary_file)
# skip first n lines from reader
for i in range(line_count):
reader.readline()

array = np.fromfile(reader, dtype=np.float32)
if fmt == 'ascii':
array = np.loadtxt(reader, dtype=np.float32)
elif fmt == 'float':
array = np.fromfile(reader, dtype=np.float32)
elif fmt == 'double':
array = np.fromfile(reader, dtype=np.float64)

if ncomp != 1:
array = array.reshape(nrows, ncols, ncomp)
else:
Expand Down
24 changes: 9 additions & 15 deletions ladybug_comfort/map/irr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
"""Methods for resolving MRT from Radiance and EnergyPlus output files."""
from __future__ import division

import numpy as np

from ladybug.sql import SQLiteResult

from ._helper import binary_to_array


def irradiance_contrib_map(
sql, direct_specular, indirect_specular, ref_specular, indirect_diffuse, ref_diffuse,
Expand Down Expand Up @@ -85,25 +89,15 @@ def irradiance_contrib_map(
diff_trans.append(d_trans)

# compute the direct irradiance contribution
direct_mtx = []
for pt_irr in _ill_vals(direct_specular):
direct_mtx.append([irr * bt for irr, bt in zip(pt_irr, beam_trans)])
direct_mtx = binary_to_array(direct_specular) * np.array(beam_trans)

# compute the indirect irradiance contribution
indirect_mtx = []
for s_irr, d_irr in zip(_ill_vals(indirect_specular), _ill_vals(indirect_diffuse)):
sen_mtx = []
for si, di, bt, dt in zip(s_irr, d_irr, beam_trans, diff_trans):
sen_mtx.append((si * bt) + (di * dt))
indirect_mtx.append(sen_mtx)
indirect_mtx = binary_to_array(indirect_specular) * np.array(
beam_trans) + binary_to_array(indirect_diffuse) * np.array(diff_trans)

# compute the ground-reflected irradiance contribution
ref_mtx = []
for s_irr, d_irr in zip(_ill_vals(ref_specular), _ill_vals(ref_diffuse)):
sen_mtx = []
for si, di, bt, dt in zip(s_irr, d_irr, beam_trans, diff_trans):
sen_mtx.append((si * bt) + (di * dt))
ref_mtx.append(sen_mtx)
ref_mtx = binary_to_array(ref_specular) * np.array(
beam_trans) + binary_to_array(ref_diffuse) * np.array(diff_trans)

return direct_mtx, indirect_mtx, ref_mtx

Expand Down
5 changes: 3 additions & 2 deletions ladybug_comfort/map/utci.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def universal_thermal_climate_index_np(ta, tr, vel, rh):
vel = np.where(vel < 0.5, 0.5, np.where(vel > 17, 17, vel))

# metrics derived from the inputs used in the polynomial equation
eh_pa = saturated_vapor_pressure_hpa_np(ta) * (rh / 100.0).astype(np.float32) # partial vapor pressure
eh_pa = saturated_vapor_pressure_hpa_np(
ta) * (rh / 100.0).astype(np.float32) # partial vapor pressure
pa_pr = eh_pa / 10.0 # convert vapour pressure to kPa
d_tr = tr - ta # difference between radiant and air temperature

Expand Down Expand Up @@ -70,7 +71,7 @@ def thermal_condition_np(utci, comfort_par):
]
choices = [-1, 1]
result = np.select(conditions, choices, default=0)

return result

def thermal_condition_eleven_point_np(utci, comfort_par):
Expand Down
Loading