Skip to content

Commit

Permalink
fix(method): random name octree for edgps calc
Browse files Browse the repository at this point in the history
  • Loading branch information
taoning committed Sep 18, 2024
1 parent a51ac88 commit 6c32b6c
Showing 1 changed file with 53 additions and 97 deletions.
150 changes: 53 additions & 97 deletions frads/methods.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Typical Radiance matrix-based simulation workflows
"""
"""Typical Radiance matrix-based simulation workflows"""

import hashlib
import logging
Expand All @@ -15,14 +14,30 @@
from pyradiance.util import parse_view
from scipy.sparse import csr_matrix

from frads.matrix import (BASIS_DIMENSION, Matrix, SensorSender, SkyReceiver,
SunMatrix, SunReceiver, SurfaceReceiver,
SurfaceSender, ViewSender, load_binary_matrix,
load_matrix, matrix_multiply_rgb,
sparse_matrix_multiply_rgb_vtds, to_sparse_matrix3)
from frads.matrix import (
BASIS_DIMENSION,
Matrix,
SensorSender,
SkyReceiver,
SunMatrix,
SunReceiver,
SurfaceReceiver,
SurfaceSender,
ViewSender,
load_binary_matrix,
load_matrix,
matrix_multiply_rgb,
sparse_matrix_multiply_rgb_vtds,
to_sparse_matrix3,
)
from frads.sky import WeaData, WeaMetaData, gen_perez_sky, parse_epw, parse_wea
from frads.utils import (minutes_to_datetime, parse_polygon, parse_rad_header,
polygon_primitive, random_string)
from frads.utils import (
minutes_to_datetime,
parse_polygon,
parse_rad_header,
polygon_primitive,
random_string,
)

logger: logging.Logger = logging.getLogger("frads.methods")

Expand Down Expand Up @@ -113,14 +128,8 @@ def __post_init__(self):
for k, v in self.matrices.items():
if isinstance(v, dict):
self.matrices[k] = MatrixConfig(**v)
if (
self.bytes == b""
and len(self.files) == 0
and len(self.matrices) == 0
):
raise ValueError(
"MaterialConfig must have either file, bytes or matrices"
)
if self.bytes == b"" and len(self.files) == 0 and len(self.matrices) == 0:
raise ValueError("MaterialConfig must have either file, bytes or matrices")


@dataclass
Expand Down Expand Up @@ -195,8 +204,7 @@ def __post_init__(self):
if self.file != "":
with open(self.file) as f:
self.data = [
[float(i) for i in line.split()]
for line in f.readlines()
[float(i) for i in line.split()] for line in f.readlines()
]
else:
raise ValueError("SensorConfig must have either file or data")
Expand Down Expand Up @@ -270,9 +278,7 @@ def __post_init__(self):
if self.file.exists() and len(self.primitives) == 0:
self.primitives = pr.parse_primitive(self.file.read_text())
elif len(self.primitives) == 0:
raise ValueError(
"SurfaceConfig must have either file or primitives"
)
raise ValueError("SurfaceConfig must have either file or primitives")


@dataclass
Expand Down Expand Up @@ -459,15 +465,10 @@ def __post_init__(self):
]:
continue
else:
raise ValueError(
f"Sensor {k} data does not match view {k} data"
)
raise ValueError(f"Sensor {k} data does not match view {k} data")
else:
self.sensors[k] = SensorConfig(
data=[
self.views[k].view.position
+ self.views[k].view.direction
]
data=[self.views[k].view.position + self.views[k].view.direction]
)

for k, v in self.windows.items():
Expand Down Expand Up @@ -515,9 +516,7 @@ def __post_init__(self):
self.settings = Settings(**self.settings)
if isinstance(self.model, dict):
self.model = Model(**self.model)
self.hash_str = hashlib.md5(str(self.__dict__).encode()).hexdigest()[
:16
]
self.hash_str = hashlib.md5(str(self.__dict__).encode()).hexdigest()[:16]

@staticmethod
def from_dict(obj: Dict[str, Any]) -> "WorkflowConfig":
Expand Down Expand Up @@ -587,16 +586,12 @@ def __init__(self, config: WorkflowConfig):
with open(self.config.settings.epw_file) as f:
self.wea_metadata, self.wea_data = parse_epw(f.read())
self.wea_header = self.wea_metadata.wea_header()
self.wea_str = self.wea_header + "\n".join(
str(d) for d in self.wea_data
)
self.wea_str = self.wea_header + "\n".join(str(d) for d in self.wea_data)
elif self.config.settings.wea_file != "":
with open(self.config.settings.wea_file) as f:
self.wea_metadata, self.wea_data = parse_wea(f.read())
self.wea_header = self.wea_metadata.wea_header()
self.wea_str = self.wea_header + "\n".join(
str(d) for d in self.wea_data
)
self.wea_str = self.wea_header + "\n".join(str(d) for d in self.wea_data)
else:
if (
self.config.settings.latitude is None
Expand Down Expand Up @@ -689,11 +684,7 @@ def get_sky_matrix(
and isinstance(dhi, (float, int))
):
_wea += str(WeaData(time, dni, dhi))
elif (
isinstance(time, list)
and isinstance(dni, list)
and isinstance(dhi, list)
):
elif isinstance(time, list) and isinstance(dni, list) and isinstance(dhi, list):
rows = [str(WeaData(t, n, d)) for t, n, d in zip(time, dni, dhi)]
_wea += "\n".join(rows)
_ncols = len(time)
Expand All @@ -716,9 +707,7 @@ def get_sky_matrix(
dtype="d",
)

def get_sky_matrix_from_wea(
self, mfactor: int, sun_only=False, onesun=False
):
def get_sky_matrix_from_wea(self, mfactor: int, sun_only=False, onesun=False):
if self.wea_str is None:
raise ValueError("No weather string available")
_sun_str = pr.gendaymtx(
Expand All @@ -741,9 +730,7 @@ def get_sky_matrix_from_wea(
daylight_hours_only=True,
mfactor=mfactor,
)
_nrows, _ncols, _ncomp, _dtype = parse_rad_header(
pr.getinfo(_matrix).decode()
)
_nrows, _ncols, _ncomp, _dtype = parse_rad_header(pr.getinfo(_matrix).decode())
return load_binary_matrix(
_matrix,
nrows=_nrows,
Expand Down Expand Up @@ -835,9 +822,7 @@ def calculate_view(
A image as a numpy array
"""
sky_matrix = self.get_sky_matrix(time, dni, dhi)
return matrix_multiply_rgb(
self.view_sky_matrices[view].array, sky_matrix
)
return matrix_multiply_rgb(self.view_sky_matrices[view].array, sky_matrix)

def calculate_sensor(
self, sensor: str, time: datetime, dni: float, dhi: float
Expand Down Expand Up @@ -913,9 +898,7 @@ def calculate_sensor_from_wea(self, sensor: str) -> np.ndarray:
raise ValueError("No wea data available")
return matrix_multiply_rgb(
self.sensor_sky_matrices[sensor].array,
self.get_sky_matrix_from_wea(
int(self.config.settings.sky_basis[-1])
),
self.get_sky_matrix_from_wea(int(self.config.settings.sky_basis[-1])),
weights=[47.4, 119.9, 11.6],
)

Expand Down Expand Up @@ -952,8 +935,7 @@ def __init__(self, config):
pr.oconv(
*config.model.materials.files,
*config.model.scene.files,
stdin=config.model.materials.bytes
+ config.model.scene.bytes,
stdin=config.model.materials.bytes + config.model.scene.bytes,
)
)
self.window_senders: Dict[str, SurfaceSender] = {}
Expand Down Expand Up @@ -1080,9 +1062,7 @@ def calculate_view(
res = []
if isinstance(bsdf, list):
if len(bsdf) != len(self.config.model.windows):
raise ValueError(
"Number of BSDF should match number of windows."
)
raise ValueError("Number of BSDF should match number of windows.")
for idx, _name in enumerate(self.config.model.windows):
_bsdf = bsdf[idx] if isinstance(bsdf, list) else bsdf
res.append(
Expand Down Expand Up @@ -1118,13 +1098,9 @@ def calculate_sensor(
res = []
if isinstance(bsdf, list):
if len(bsdf) != len(self.config.model.windows):
raise ValueError(
"Number of BSDF should match number of windows."
)
raise ValueError("Number of BSDF should match number of windows.")
for idx, _name in enumerate(self.config.model.windows):
_bsdf = self.config.model.materials.matrices[
bsdf[_name]
].matrix_data
_bsdf = self.config.model.materials.matrices[bsdf[_name]].matrix_data
res.append(
matrix_multiply_rgb(
self.sensor_window_matrices[sensor].array[idx],
Expand Down Expand Up @@ -1237,13 +1213,9 @@ def calculate_surface(
sky_matrix = self.get_sky_matrix(
time, dni, dhi, solar_spectrum=solar_spectrum
)
res = np.zeros(
(self.surface_senders[surface].yres, sky_matrix.shape[1])
)
res = np.zeros((self.surface_senders[surface].yres, sky_matrix.shape[1]))
for idx, _name in enumerate(self.config.model.windows):
_bsdf = self.config.model.materials.matrices[
bsdf[_name]
].matrix_data
_bsdf = self.config.model.materials.matrices[bsdf[_name]].matrix_data
res += matrix_multiply_rgb(
self.surface_window_matrices[surface].array[idx],
_bsdf,
Expand Down Expand Up @@ -1293,14 +1265,12 @@ def calculate_edgps(
gmaterial = _gms[sname]
stdins.append(gmaterial.bytes)
for prim in self.window_senders[wname].surfaces:
stdins.append(
replace(prim, modifier=gmaterial.identifier).bytes
)
stdins.append(replace(prim, modifier=gmaterial.identifier).bytes)
if (_pgs := self.config.model.windows[wname].proxy_geometry) != {}:
for prim in _pgs[sname]:
stdins.append(prim.bytes)

octree = "test.oct"
octree = f"{random_string(5)}.oct"
with open(octree, "wb") as f:
f.write(pr.oconv(stdin=b"".join(stdins), octree=self.octree))

Expand Down Expand Up @@ -1385,9 +1355,7 @@ def __init__(self, config: WorkflowConfig):
pr.oconv(
*config.model.materials.files,
*config.model.scene.files,
stdin=(
config.model.materials.bytes + config.model.scene.bytes
),
stdin=(config.model.materials.bytes + config.model.scene.bytes),
)
)
self.blacked_out_octree: Path = self.octdir / f"{random_string(5)}.oct"
Expand Down Expand Up @@ -1425,9 +1393,7 @@ def _gen_blacked_out_octree(self):
pr.xform(s, modifier="black") for s in self.config.model.scene.files
)
if self.config.model.scene.bytes != b"":
black_scene += pr.xform(
self.config.model.scene.bytes, modifier="black"
)
black_scene += pr.xform(self.config.model.scene.bytes, modifier="black")
black = pr.Primitive("void", "plastic", "black", [], [0, 0, 0, 0, 0])
glow = pr.Primitive("void", "glow", "glowing", [], [1, 1, 1, 0])
with open(self.blacked_out_octree, "wb") as f:
Expand Down Expand Up @@ -1531,9 +1497,7 @@ def _prepare_sun_receivers(self):
parse_polygon(r.surfaces[0]).normal.tobytes()
for r in self.window_receivers.values()
]
unique_window_normals = [
np.frombuffer(arr) for arr in set(window_normals)
]
unique_window_normals = [np.frombuffer(arr) for arr in set(window_normals)]
self.sensor_sun_receiver = SunReceiver(
self.config.settings.sun_basis,
sun_matrix=self.direct_sun_matrix,
Expand Down Expand Up @@ -1585,14 +1549,10 @@ def _prepare_mapping_octrees(self):
blacked_out_windows = str(black) + " ".join(blacked_out_windows)
glowing_windows = str(glow) + " ".join(glowing_windows)
with open(self.vmap_oct, "wb") as wtr:
wtr.write(
pr.oconv(stdin=glowing_windows.encode(), octree=self.octree)
)
wtr.write(pr.oconv(stdin=glowing_windows.encode(), octree=self.octree))
logger.info("Generating view matrix material map octree")
with open(self.cdmap_oct, "wb") as wtr:
wtr.write(
pr.oconv(stdin=blacked_out_windows.encode(), octree=self.octree)
)
wtr.write(pr.oconv(stdin=blacked_out_windows.encode(), octree=self.octree))

def generate_matrices(self):
if self.mfile.exists():
Expand Down Expand Up @@ -1731,9 +1691,7 @@ def calculate_sensor_from_wea(self, sensor):
)
direct_sky_matrix = to_sparse_matrix3(direct_sky_matrix)
res3 = np.zeros((self.sensor_senders[sensor].yres, sky_matrix.shape[1]))
res3d = np.zeros(
(self.sensor_senders[sensor].yres, sky_matrix.shape[1])
)
res3d = np.zeros((self.sensor_senders[sensor].yres, sky_matrix.shape[1]))
for idx, _name in enumerate(self.config.model.windows):
res3 += matrix_multiply_rgb(
self.sensor_window_matrices[sensor].array[idx],
Expand All @@ -1749,9 +1707,7 @@ def calculate_sensor_from_wea(self, sensor):
direct_sky_matrix,
weights=[47.4, 119.9, 11.6],
)
rescd = np.zeros(
(self.sensor_senders[sensor].yres, sky_matrix.shape[1])
)
rescd = np.zeros((self.sensor_senders[sensor].yres, sky_matrix.shape[1]))
for c, w in enumerate([47.4, 119.9, 11.6]):
rescd += w * np.dot(
self.sensor_sun_direct_matrices[sensor].array[c],
Expand Down

0 comments on commit 6c32b6c

Please sign in to comment.