Skip to content

Commit

Permalink
Merge pull request #3 from LBNL-ETA/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
taoning committed Feb 9, 2023
2 parents 2bcc072 + 425bd1b commit b60046a
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 11 deletions.
7 changes: 6 additions & 1 deletion pyradiance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)

from .gen import (
genblinds,
genbsdf,
gendaylit,
gendaymtx,
Expand Down Expand Up @@ -57,6 +58,7 @@

from .rt import (
RcModifier,
mkpmap,
rcontrib,
rpict,
rtrace,
Expand All @@ -71,6 +73,7 @@
get_image_dimensions,
getinfo,
rcode_depth,
rcode_ident,
rcode_norm,
render,
rfluxmtx,
Expand Down Expand Up @@ -99,6 +102,7 @@
"bsdf2ttree",
"cnt",
"dctimestep",
"genblinds",
"genbsdf",
"gendaylit",
"gendaymtx",
Expand All @@ -111,6 +115,7 @@
"read_rad",
"mgf2rad",
"mkillum",
"mkpmap",
"obj2rad",
"oconv",
"pabopto2bsdf",
Expand All @@ -120,6 +125,7 @@
"pcond",
"pfilt",
"rcode_depth",
"rcode_ident",
"rcode_norm",
"rcontrib",
"read_rad",
Expand All @@ -138,7 +144,6 @@
"Sensor",
"SamplingParameters",
"View",
"load_views",
"parse_primitive",
"wrapbsdf",
"xform",
Expand Down
35 changes: 35 additions & 0 deletions pyradiance/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,41 @@
BINPATH = Path(__file__).parent / "bin"


def genblinds(
mat: str,
name: str,
depth: float,
width: float,
height: float,
nslats: int,
angle: float,
rcurv: Optional[float] = None,
) -> bytes:
"""Generate a RADIANCE description of venetian blinds.
Args:
mat: Material name
name: Name of the blinds
depth: Depth of the blinds
width: Width of the blinds
height: Height of the blinds
nslats: Number of slats
angle: Angle of the slats
rcurv: Radius of curvature of the slats, + for upward curvature, - for downward
Returns:
bytes: RADIANCE description of the blinds
"""
cmd = [BINPATH / "genblinds", mat, name, str(depth), str(width), str(height)]
cmd.extend([str(nslats), str(angle)])
if rcurv is not None:
if rcurv > 0:
cmd.extend(["+r", str(rcurv)])
else:
cmd.extend(["-r", str(rcurv)])
return sp.run(cmd, check=True, stdout=sp.PIPE).stdout


def genbsdf(
*inp: Union[str, Path],
nsamp: int = 1,
Expand Down
17 changes: 9 additions & 8 deletions pyradiance/px.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import subprocess as sp
from typing import List, Optional, Union


BINPATH = Path(__file__).parent / "bin"


Expand Down Expand Up @@ -252,7 +253,7 @@ def pvaluer(
pic: Union[Path, str, bytes],
xres: Optional[int] = None,
yres: Optional[int] = None,
inpformat: str = "a",
inform: str = "a",
resstr: bool = True,
dataonly: bool = False,
header: bool = False,
Expand All @@ -264,15 +265,15 @@ def pvaluer(
constructing a image from pixel values.
Args:
pic: Path to Radiance picture file or bytes of the picture file.
xres: Number of columns in the picture file.
yres: Number of rows in the picture file.
inpformat: Radiance picture file format. Default is "a" for ascii.
pic: Path or bytes of the input pixel data.
xres: X resolution.
yres: Y resolution.
inform: input data format. Default is "a" for ascii.
header: Set to True if the picture file has a header. Default is False.
primaries: List of primaries for XYZ calculation. Default is None.
pxyz: Set to True to calculate XYZ values. Default is False.
Returns:
Bytes of the pvalue output (Radiance .
Bytes of the pvalue output
"""
stdin = None
cmd = ["pvalue", "-r"]
Expand All @@ -282,8 +283,8 @@ def pvaluer(
cmd.append("-H")
if dataonly:
cmd.append("-d")
if inpformat != "a":
cmd.append(f"-d{inpformat}")
if inform != "a":
cmd.append(f"-d{inform}")
if yres:
sign = "-" if yres > 0 else "+"
cmd.extend([f"{sign}y", str(abs(yres))])
Expand Down
154 changes: 153 additions & 1 deletion pyradiance/rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pathlib import Path
import subprocess as sp
import sys
from typing import Optional, Sequence, Union
from typing import Optional, Sequence, Tuple, Union


BINPATH = Path(__file__).parent / "bin"
Expand Down Expand Up @@ -70,6 +70,158 @@ def args(self):
return arglist


def mkpmap(
octree: Union[Path, str],
global_map: Optional[Tuple[Union[Path, str], int]] = None,
caustic_map: Optional[Tuple[Union[Path, str], int]] = None,
volume_map: Optional[Tuple[Union[Path, str], int]] = None,
direct_map: Optional[Tuple[Union[Path, str], int]] = None,
contrib_map: Optional[Tuple[Union[Path, str], int]] = None,
pre_global_map: Optional[Tuple[Union[Path, str], int, float]] = None,
predistrib: Optional[float] = None,
rect_region: Tuple[float, float, float, float, float, float] = None,
sphere_region: Tuple[float, float, float, float] = None,
maxbounce: Optional[int] = None,
maxprepass: Optional[int] = None,
port_mod: Optional[Sequence[str]] = None,
port_modfile: Optional[str] = None,
precomp: Optional[float] = None,
seed: Optional[int] = None,
virtual_mod: Optional[Sequence[str]] = None,
virtual_modfile: Optional[str] = None,
amb_excl_mod: Optional[str] = None,
amb_excl_modfile: Optional[str] = None,
amb_incl_mod: Optional[str] = None,
amb_incl_modfile: Optional[str] = None,
backface_vis: bool = False,
sample_res: Optional[int] = None,
partition_size: Optional[float] = None,
progress_file: Optional[str] = None,
overwrite: bool = False,
maxdist: Optional[float] = None,
scattering_albedo: Optional[Tuple[float, float, float]] = None,
extinction_coefficient: Optional[Tuple[float, float, float]] = None,
scattering_eccentricity: Optional[float] = None,
nproc: int = 1,
progress_interval: Optional[int] = None,
) -> None:
"""
Mkpmap takes a RADIANCE scene description as an octree and performs
Monte Carlo forward path tracing from the light sources, depositing
indirect ray hitpoints along with their energy (flux) as "photons".
The resulting localised energy distribution represents a global
illumination solution which is written to a file for subsequent evaluation
by rpict(1), rtrace(1) and rvu(1) in a backward raytracing pass.
The photon map(s) can be reused for multiple viewpoints and sensor
locations as long as the geometry remains unchanged.
Args:
octree: Octree file path.
global_map: Global map file path and number of photons.
caustic_map: Caustic map file path and number of photons.
volume_map: Volume map file path and number of photons.
direct_map: Direct map file path and number of photons.
contrib_map: Contribution map file path and number of photons.
pre_global_map: Precomputed global map file path, number of photons and bandwidth.
predistrib: Photon predistribution factor.
rect_region: Rectangular region
sphere_region: Spherical region
maxbounce: Maximum number of bounces.
maxprepass: Maximum number of iteratiosn of distributoin prepass before terminating.
port_mod: Specifies a modifier to act as a photon port.
port_modfile: File with modifiers to act as photon ports.
precomp: Fraction of global photons to precompute.
seed: Random seed.
virtual_mod: Specifies a modifier to act as a virtual source.
virtual_modfile: File with modifiers to act as virtual sources.
amb_excl_mod: Specifies a modifier to exclude from ambient calculation.
amb_excl_modfile: File with modifiers to exclude from ambient calculation.
amb_incl_mod: Specifies a modifier to include in ambient calculation.
amb_incl_modfile: File with modifiers to include in ambient calculation.
backface_vis: Backface visibility.
sample_res: Sample resolution.
"""
cmd = [str(BINPATH / "mkpmap")]
if global_map is not None:
cmd.extend(["-apg", str(global_map[0]), str(global_map[1])])
if caustic_map is not None:
cmd.extend(["-apc", str(caustic_map[0]), str(caustic_map[1])])
if volume_map is not None:
cmd.extend(["-apv", str(volume_map[0]), str(volume_map[1])])
if direct_map is not None:
cmd.extend(["-apd", str(direct_map[0]), str(direct_map[1])])
if contrib_map is not None:
cmd.extend(["-apC", str(contrib_map[0]), str(contrib_map[1])])
if pre_global_map is not None:
cmd.extend(
[
"-app",
str(pre_global_map[0]),
str(pre_global_map[1]),
str(pre_global_map[2]),
]
)
if precomp is not None:
cmd.extend(["-apP", str(precomp)])
if predistrib is not None:
cmd.extend(["-apD", str(predistrib)])
if rect_region is not None:
cmd.extend(["-api", *map(str, rect_region)])
elif sphere_region is not None:
cmd.extend(["-apI", *map(str, sphere_region)])
if maxbounce is not None:
cmd.extend(["-lr", str(maxbounce)])
if maxprepass is not None:
cmd.extend(["-apM", str(maxprepass)])
if port_mod is not None:
for mod in port_mod:
cmd.extend(["-apo", mod])
elif port_modfile is not None:
cmd.extend(["-apO", port_modfile])
if seed is not None:
cmd.extend(["-apr", str(seed)])
if virtual_mod is not None:
for mod in virtual_mod:
cmd.extend(["-aps", mod])
elif virtual_modfile is not None:
cmd.extend(["-apS", virtual_modfile])
if amb_excl_mod is not None:
for mod in amb_excl_mod:
cmd.extend(["-ae", mod])
elif amb_excl_modfile is not None:
cmd.extend(["-aE", amb_excl_modfile])
elif amb_incl_mod is not None:
for mod in amb_incl_mod:
cmd.extend(["-ai", mod])
elif amb_incl_modfile is not None:
cmd.extend(["-aI", amb_incl_modfile])
if backface_vis:
cmd.append("-bv+")
if sample_res is not None:
cmd.extend(["-dp", str(sample_res)])
if partition_size is not None:
cmd.extend(["-ds", str(partition_size)])
if progress_file is not None:
cmd.extend(["-e", progress_file])
if overwrite:
cmd.append("-fo+")
if maxdist is not None:
cmd.extend(["-ld", str(maxdist)])
if scattering_albedo is not None:
cmd.extend(["-ma", *map(str, scattering_albedo)])
if extinction_coefficient is not None:
cmd.extend(["-me", *map(str, extinction_coefficient)])
if scattering_eccentricity is not None:
cmd.extend(["-mg", str(scattering_eccentricity)])
cmd.extend(["-n", str(nproc)])
if progress_interval is not None:
cmd.extend(["-t", str(progress_interval)])
cmd.append(str(octree))
sp.run(cmd, check=True, stdout=sp.PIPE).stdout


def rcontrib(
inp: bytes,
octree: Union[Path, str],
Expand Down
67 changes: 67 additions & 0 deletions pyradiance/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,73 @@ def rcode_depth(
return sp.run(cmd, stdout=sp.PIPE, input=stdin, check=True).stdout


def rcode_ident(
inp: Union[str, Path, bytes],
index_size: int = 16,
sep: str = "\n",
decode: bool = False,
header: bool = True,
xres: Optional[int] = None,
yres: Optional[int] = None,
resstr: bool = True,
identifiers: bool = False,
indexes: bool = False,
per_point: bool = False,
flush: bool = False,
) -> bytes:
"""Store identifiers in an indexed map and retrieve from same
Args:
inp: input file or bytes
index_size: index size
sep: separator
decode: Set to True to decode instead
header: Set to False to not to expect header on input;
or not to include header on output when decoding
xres: x resolution
yres: y resolution
resstr: Set to False to not include resolution string on output
identifiers: Set to True to include identifiers on output
indexes: Set to True to instead list identifiers indexes on output
per_point: Set to True to compute per point instead of per pixel
flush: Set to True to flush output after each identifier
Returns:
bytes: output of rcode_ident
"""
cmd = [str(BINPATH / "rcode_ident")]
if decode:
cmd.append("-r")
if not resstr:
cmd.append("-H")
if identifiers:
cmd.append("-l")
elif indexes:
cmd.append("-n")
if per_point:
cmd.append("-i")
if flush:
cmd.append("-u")
else:
if index_size not in (8, 16, 24):
raise ValueError("index_size must be 8, 16, or 24")
cmd.append(f"-{index_size}")
if xres:
cmd.extend(["-x", str(xres)])
if yres:
cmd.extend(["-y", str(yres)])
if not header:
cmd.append("-h")
if sep != "\n":
cmd.append(f"-t{sep}")
stdin = None
if isinstance(inp, bytes):
stdin = inp
elif isinstance(inp, (str, Path)):
cmd.append(str(inp))
else:
raise TypeError("inp must be a string, Path, or bytes")
return sp.run(cmd, stdout=sp.PIPE, input=stdin, check=True).stdout


def rcode_norm(
inp,
inheader: bool = True,
Expand Down

0 comments on commit b60046a

Please sign in to comment.