Skip to content

Commit

Permalink
Merge pull request princeton-vl#305 from princeton-vl/f_integration_test
Browse files Browse the repository at this point in the history
Fix integration test bugs
  • Loading branch information
pvl-bot authored Oct 18, 2024
2 parents b6a65b8 + d971819 commit ee415db
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 48 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ blender
blender.tar.xz
Blender.app

.nfs*

*.c

.coverage
Expand Down
2 changes: 1 addition & 1 deletion infinigen/assets/utils/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def obj2polygon(obj):
for p in obj.data.polygons
]
)
return shapely.make_valid(shapely.simplify(p, 1e-6))
return shapely.ops.orient(shapely.make_valid(shapely.simplify(p, 1e-6)))


def buffer(p, distance):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def canonicalize(self, p):
break
if not is_valid_polygon(p):
raise NotImplementedError("Invalid polygon")
return p
return orient(p)
except AttributeError:
raise NotImplementedError("Invalid multi polygon")

Expand Down
6 changes: 4 additions & 2 deletions infinigen/core/constraints/example_solver/room/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,14 @@ def decorate(self, state):
quad_segs = (
1 if corner_func == "sharp" else np.random.randint(4, 7)
)
exterior_ = (
exterior_ = self.constants.canonicalize(
exterior.difference(cutter)
.union(shapely.Point(q).buffer(length, quad_segs=quad_segs))
.buffer(0)
)
new = state[k].polygon.intersection(exterior_).buffer(0)
new = self.constants.canonicalize(
state[k].polygon.intersection(exterior_).buffer(0)
)
if all(
new.buffer(-m + 1e-2).geom_type == "Polygon"
for m in np.linspace(0, 0.75, 4)
Expand Down
4 changes: 2 additions & 2 deletions infinigen/core/constraints/example_solver/room/decorate.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from infinigen.core.surface import write_attr_data
from infinigen.core.util import blender as butil
from infinigen.core.util.blender import deep_clone_obj
from infinigen.core.util.math import int_hash
from infinigen.core.util.math import FixedSeed, int_hash
from infinigen.core.util.random import log_uniform
from infinigen.core.util.random import random_general as rg

Expand Down Expand Up @@ -93,7 +93,7 @@ def split_rooms(rooms_meshed: list[bpy.types.Object]):


def import_material(factory_name):
with gin.unlock_config():
with gin.unlock_config(), FixedSeed(0):
try:
return importlib.import_module(f"infinigen.assets.materials.{factory_name}")
except ImportError:
Expand Down
6 changes: 4 additions & 2 deletions infinigen/core/constraints/example_solver/room/solidifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from infinigen.core.util.random import random_general as rg

from .base import RoomGraph, room_type, valid_rooms
from .utils import mls_ccw

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -210,7 +211,8 @@ def solidify(self, state):
}
exterior = next(k for k in state.objs if room_type(k) == Semantics.Exterior)
exterior_edges = {
r.target_name: canonicalize_mls(r.value) for r in state[exterior].relations
r.target_name: mls_ccw(canonicalize_mls(r.value), state, r.target_name)
for r in state[exterior].relations
}
exterior_buffer = shapely.simplify(
state[exterior].polygon.buffer(-wt / 2 - _eps, join_style="mitre"), 1e-3
Expand Down Expand Up @@ -538,7 +540,7 @@ def make_door_cutter(self, mls, direction):
wt = self.constants.wall_thickness
cutter.scale = (
self.constants.door_width / 2,
self.constants.door_width / 2 + wt,
self.constants.door_width + wt / 2,
self.constants.door_size / 2 - _snap / 2,
)
cutter.location[-1] += _snap / 2
Expand Down
12 changes: 12 additions & 0 deletions infinigen/core/constraints/example_solver/room/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ def update_exterior(state: State, i: str):
r.value = MultiLineString(v)


def mls_ccw(mls: MultiLineString, state: State, i: str):
exterior = state[i].polygon.exterior
coords = np.array(exterior.coords[:-1])
mls_ = []
for ls in mls.geoms:
u, v = ls.coords[:2]
x = np.argmin(np.linalg.norm(coords - np.array(u)[np.newaxis], axis=-1))
y = np.argmin(np.linalg.norm(coords - np.array(v)[np.newaxis], axis=-1))
mls_.append(ls if x < y else shapely.reverse(ls))
return MultiLineString(mls_)


def update_staircase(state: State, i: str):
pholder = room_name(Semantics.Staircase, room_level(i))
r = next(r for r in state[pholder].relations if r.target_name == i)
Expand Down
2 changes: 1 addition & 1 deletion infinigen/core/constraints/example_solver/state_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def __repr__(self):
obj = self.obj
tags = self.tags
relations = self.relations
return f"{self.__class__.__name__}(obj.name={obj.name if obj is not None else obj.name}, polygon={self.polygon}, {tags=}, {relations=})"
return f"{self.__class__.__name__}(obj.name={obj.name if obj is not None else None}, polygon={self.polygon}, {tags=}, {relations=})"


@dataclass
Expand Down
5 changes: 3 additions & 2 deletions infinigen_examples/generate_individual_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,9 @@ def build_and_save_asset(payload: dict):
)

if args.cam_center > 0 and asset:
co = read_base_co(asset) + asset.location
center.location = (np.amin(co, 0) + np.amax(co, 0)) / 2
co = read_base_co(asset)
location = (np.amin(co, 0) + np.amax(co, 0)) / 2
center.location = (np.array(asset.matrix_world) @ np.array([*location, 1]))[:-1]
center.location[-1] += args.cam_zoff

if args.cam_dist <= 0 and asset:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,11 @@ def parse_scene_log(
"blendergt": [],
}

log_folder = scene_path/"logs"
coarse_folder = scene_path/"coarse"
fine_folder = scene_path/"fine"

if not (
log_folder.exists()
and coarse_folder.exists()
and fine_folder.exists()
):
log_folder = scene_path / "logs"
coarse_folder = scene_path / "coarse"
fine_folder = scene_path / "fine"

if not (log_folder.exists() and coarse_folder.exists() and fine_folder.exists()):
return ret_dict

for filepath in log_folder.glob("*.err"):
Expand Down Expand Up @@ -133,11 +129,12 @@ def parse_scene_log(
"gt_time": gt_time,
}

fine_poly = parse_poly_file(fine_folder/"polycounts.txt")
fine_poly = parse_poly_file(fine_folder / "polycounts.txt")
ret_dict["gen_triangles"] = fine_poly.get("Triangles", "NAN")

return ret_dict


def parse_poly_file(path):
res = {}

Expand All @@ -153,18 +150,20 @@ def parse_poly_file(path):

return res

def parse_asset_log(asset_path):

poly = parse_poly_file(asset_path/"polycounts.txt")
def parse_asset_log(asset_path):
poly = parse_poly_file(asset_path / "polycounts.txt")

return {
"triangles": poly.get("Tris", "NAN"),
"gen_mem": poly.get("Memory", "NAN"),
}


def format_stats(d):
return ", ".join(f"{k}: {v}" for k, v in d.items())


def parse_run_df(run_path: Path):
runs = {
"_".join((x.name.split("_")[2:])): x for x in run_path.iterdir() if x.is_dir()
Expand Down Expand Up @@ -255,34 +254,28 @@ def find_run(base_path: str, run: str) -> Path:


def fuzzy_merge(dfA, dfB, keyA, keyB, threshold=1):

from rapidfuzz import fuzz, process

matches_A = []
matches_B = []


def preproc(x):
x = x.split('/')[-1]
x = re.sub(r'(?<!^)(?=[A-Z][a-z])', '_', x)
x = x.split("/")[-1]
x = re.sub(r"(?<!^)(?=[A-Z][a-z])", "_", x)
x = x.lower()
return x

b_names_list = dfB[keyB].apply(preproc)
print(list(b_names_list))

for i, rowA in dfA.iterrows():

match = process.extractOne(
preproc(rowA[keyA]),
b_names_list,
scorer=fuzz.ratio,
score_cutoff=threshold
preproc(rowA[keyA]), b_names_list, scorer=fuzz.ratio, score_cutoff=threshold
)

if match:
matched_rowB = dfB.loc[match[2]].to_dict()
#print(f"Matched {rowA[keyA].split('/')[-1]} with {matched_rowB[keyB].split('/')[-1]} with score {match[1]:.2f}")
# print(f"Matched {rowA[keyA].split('/')[-1]} with {matched_rowB[keyB].split('/')[-1]} with score {match[1]:.2f}")
else:
matched_rowB = {col: pd.NA for col in dfB.columns}
matched_rowB[keyB] = "No Matching Scene"
Expand All @@ -291,22 +284,26 @@ def preproc(x):
matches_A.append(rowA.to_dict())
matches_B.append(matched_rowB)

dfA_matched = pd.DataFrame(matches_A).add_suffix('_A')
dfB_matched = pd.DataFrame(matches_B).add_suffix('_B')
dfA_matched = pd.DataFrame(matches_A).add_suffix("_A")
dfB_matched = pd.DataFrame(matches_B).add_suffix("_B")

merged_df = pd.concat([dfA_matched, dfB_matched], axis=1)

return merged_df
return merged_df


def main():
parser = argparse.ArgumentParser()
parser.add_argument("base_path", type=Path)
parser.add_argument("--compare_runs", type=str, nargs="+")
parser.add_argument("compare_runs", type=Path, nargs="+")
parser.add_argument("--nearest", action="store_true")
args = parser.parse_args()

runs_folder = args.base_path / "runs"
views_folder = args.base_path / "views"
for run in args.compare_runs:
if not run.exists():
raise FileNotFoundError(f"Could not find {run}")

runs_folder = args.compare_runs[0].parent
views_folder = runs_folder.parent / "views"

runs = [find_run(runs_folder, run) for run in args.compare_runs]

Expand All @@ -327,10 +324,13 @@ def main():

if args.nearest:
main_df = fuzzy_merge(lhs, rhs, keyA="name", keyB="name", threshold=80)
main_df["name_A"] = main_df["name"]
main_df["name_B"] = main_df["name"]
else:
main_df = lhs.merge(rhs, on="name", suffixes=("_A", "_B"), how="outer")
main_df["name_A"] = main_df["name"]
main_df["name_B"] = main_df["name"]

assert "name_A" in main_df.columns
assert "name_B" in main_df.columns

for col in main_df:
if col.startswith("img_path"):
Expand Down Expand Up @@ -367,7 +367,7 @@ def main():
)

# Save the rendered HTML to a file
name = "_".join(args.compare_runs) + ".html"
name = "_".join([p.name for p in args.compare_runs]) + ".html"
output_path = views_folder / name
print("Writing to ", output_path)
output_path.write_text(html_content)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
OUTPUT_PATH=$1

if [ -z "$OUTPUT_PATH" ]; then
echo "Please provide an output path"
exit 1
fi

# Environment Variables for Opting In/Out
RUN_INDOOR=${RUN_INDOOR:-1}
RUN_NATURE=${RUN_NATURE:-1}
Expand All @@ -10,8 +17,7 @@ COMMIT_HASH=$(git rev-parse HEAD | cut -c 1-6)
DATE=$(date '+%Y-%m-%d')
JOBTAG="${DATE}_ifg-int"
BRANCH=$(git rev-parse --abbrev-ref HEAD | sed 's/_/-/g')
VERSION_STRING="${DATE}_${INFINIGEN_VERSION}_${BRANCH}_${COMMIT_HASH}_${USER}"
OUTPUT_PATH=/n/fs/pvl-renders/integration_test/runs/
VERSION_STRING="${DATE}_${BRANCH}_${COMMIT_HASH}_${USER}"

mkdir -p $OUTPUT_PATH
OUTPUT_PATH=$OUTPUT_PATH/$VERSION_STRING
Expand All @@ -20,10 +26,10 @@ OUTPUT_PATH=$OUTPUT_PATH/$VERSION_STRING
if [ "$RUN_INDOOR" -eq 1 ]; then
for indoor_type in DiningRoom Bathroom Bedroom Kitchen LivingRoom; do
python -m infinigen.datagen.manage_jobs --output_folder $OUTPUT_PATH/${JOBTAG}_scene_indoor_$indoor_type \
--num_scenes 3 --cleanup big_files --configs singleroom --overwrite \
--num_scenes 3 --cleanup big_files --configs singleroom.gin fast_solve.gin --overwrite \
--pipeline_configs slurm_1h monocular indoor_background_configs.gin \
--pipeline_overrides get_cmd.driver_script=infinigen_examples.generate_indoors sample_scene_spec.seed_range=[0,100] slurm_submit_cmd.slurm_nodelist=$NODECONF \
--overrides compose_indoors.terrain_enabled=True restrict_solving.restrict_parent_rooms=\[\"$indoor_type\"\] compose_indoors.solve_small_enabled=False &
--overrides compose_indoors.terrain_enabled=True restrict_solving.restrict_parent_rooms=\[\"$indoor_type\"\] &
done
fi

Expand Down

0 comments on commit ee415db

Please sign in to comment.