From 6065a0736dcbbc098938908231efa2f4f73269fd Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Fri, 20 Dec 2024 12:31:00 +0000 Subject: [PATCH 01/13] Generate GT and display normal maps during integration test viewer --- tests/integration/launch.sh | 4 ++-- tests/integration/template.html | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/integration/launch.sh b/tests/integration/launch.sh index fbb1ba22..0071aa90 100644 --- a/tests/integration/launch.sh +++ b/tests/integration/launch.sh @@ -30,7 +30,7 @@ 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.gin fast_solve.gin --overwrite \ - --pipeline_configs slurm monocular indoor_background_configs.gin \ + --pipeline_configs slurm monocular blender_gt 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\"\] & done @@ -42,7 +42,7 @@ if [ "$RUN_NATURE" -eq 1 ]; then python -m infinigen.datagen.manage_jobs --output_folder $OUTPUT_PATH/${JOBTAG}_scene_nature_$nature_type \ --num_scenes 3 --cleanup big_files --overwrite \ --configs $nature_type.gin dev.gin \ - --pipeline_configs slurm monocular \ + --pipeline_configs slurm monocular blender_gt \ --pipeline_overrides sample_scene_spec.seed_range=[0,100] & done fi diff --git a/tests/integration/template.html b/tests/integration/template.html index 01dbb080..0f45a681 100644 --- a/tests/integration/template.html +++ b/tests/integration/template.html @@ -114,6 +114,7 @@

{{ heading }}

{{scene['name_A']}}

+

{{scene['stats_A']}}

@@ -121,6 +122,7 @@

{{ heading }}

{{scene['name_B']}}

+

{{scene['stats_B']}}

@@ -143,6 +145,7 @@

{{ heading }}

{{scene['name_A']}}

+

{{scene['stats_A']}}

@@ -150,6 +153,7 @@

{{ heading }}

{{scene['name_B']}}

+

{{scene['stats_B']}}

From 05994a949a8e0b847e0cc07beaadb44887aece90 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Fri, 20 Dec 2024 12:39:23 +0000 Subject: [PATCH 02/13] Sanitize / in branchnames for integration test path --- tests/integration/launch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/launch.sh b/tests/integration/launch.sh index 0071aa90..036101a0 100644 --- a/tests/integration/launch.sh +++ b/tests/integration/launch.sh @@ -19,7 +19,7 @@ INFINIGEN_VERSION=$(python -c "import infinigen; print(infinigen.__version__)") 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') +BRANCH=$(git rev-parse --abbrev-ref HEAD | sed 's/_/-/g; s/\//_/g') VERSION_STRING="${DATE}_${BRANCH}_${COMMIT_HASH}_${USER}" mkdir -p $OUTPUT_PATH From 709e293f903868a9711139163998a3218b12ea23 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Sun, 22 Dec 2024 12:14:13 +0000 Subject: [PATCH 03/13] Add continue for missing logfile in david's parse_scene_log --- tests/integration/compare.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/compare.py b/tests/integration/compare.py index a2ea0bd4..ee882008 100644 --- a/tests/integration/compare.py +++ b/tests/integration/compare.py @@ -69,7 +69,11 @@ def parse_scene_log( else: continue - text = filepath.read_text() + try: + text = filepath.read_text() + except FileNotFoundError: + continue + if "[MAIN TOTAL] finished in" not in text: continue search = re.search( From c4b2253044b1330bd7e06209d2433ba378e4b9a7 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Sun, 22 Dec 2024 12:38:13 +0000 Subject: [PATCH 04/13] Add optional output path for integration_test compare --- tests/integration/compare.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/compare.py b/tests/integration/compare.py index ee882008..c2683a37 100644 --- a/tests/integration/compare.py +++ b/tests/integration/compare.py @@ -300,6 +300,7 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument("compare_runs", type=Path, nargs="+") parser.add_argument("--nearest", action="store_true") + parser.add_argument("--output_path", type=Path, default=None) args = parser.parse_args() for run in args.compare_runs: @@ -372,7 +373,10 @@ def main(): # Save the rendered HTML to a file name = "_".join([p.name for p in args.compare_runs]) + ".html" - output_path = views_folder / name + + output_path = args.output_path + if output_path is None: + output_path = views_folder / name print("Writing to ", output_path) output_path.write_text(html_content) From 068e0525e25726a3a8307cf4709bb592d39543f6 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Sun, 22 Dec 2024 12:39:43 +0000 Subject: [PATCH 05/13] Run checks on draft PRs, deactivate CODEOWNERS --- .github/{CODEOWNERS => backup_CODEOWNERS} | 0 .github/workflows/checks.yml | 1 - 2 files changed, 1 deletion(-) rename .github/{CODEOWNERS => backup_CODEOWNERS} (100%) diff --git a/.github/CODEOWNERS b/.github/backup_CODEOWNERS similarity index 100% rename from .github/CODEOWNERS rename to .github/backup_CODEOWNERS diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index e6ebf622..2e262b7a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -22,7 +22,6 @@ env: jobs: checks: - if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: From 2319d66e6dea5a9c75aee99ed6909b8aa87082e7 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Sun, 22 Dec 2024 16:34:14 +0000 Subject: [PATCH 06/13] Fix outtdated bbox input to camera_pose_proposal --- infinigen/core/placement/camera.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/infinigen/core/placement/camera.py b/infinigen/core/placement/camera.py index 17f90948..a6f78780 100644 --- a/infinigen/core/placement/camera.py +++ b/infinigen/core/placement/camera.py @@ -408,7 +408,10 @@ def __call__(self, camera_rig, frame_curr, retry_pct, bvh): bbox = (camera_rig.location - margin, camera_rig.location + margin) for _ in range(self.retries): - res = camera_pose_proposal(bvh, bbox) # ! + res = camera_pose_proposal( + scene_bvh=bvh, + location_sample=lambda: np.random.uniform(*bbox), + ) if res is None: continue dist = np.linalg.norm(np.array(res.loc) - np.array(camera_rig.location)) From 81c74b4c8c75f06d465e3fabb3ff7cd3da11a107 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Sun, 22 Dec 2024 16:40:55 +0000 Subject: [PATCH 07/13] Fix ignored GT samples setting due to incorrectly scoped gin config --- infinigen/core/rendering/render.py | 6 +++++- infinigen_examples/configs_nature/base.gin | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/infinigen/core/rendering/render.py b/infinigen/core/rendering/render.py index 43cc44d8..8c970e24 100644 --- a/infinigen/core/rendering/render.py +++ b/infinigen/core/rendering/render.py @@ -389,11 +389,12 @@ def render_image( camera: bpy.types.Object, frames_folder, passes_to_save, - flat_shading=False, render_resolution_override=None, excludes=[], use_dof=False, dof_aperture_fstop=2.8, + flat_shading=False, + override_num_samples=None, ): tic = time.time() @@ -408,6 +409,9 @@ def render_image( camrig_id, subcam_id = cam_util.get_id(camera) + if override_num_samples is not None: # usually used for GT + bpy.context.scene.cycles.samples = override_num_samples + if flat_shading: with Timer("Set object indices"): object_data = set_pass_indices() diff --git a/infinigen_examples/configs_nature/base.gin b/infinigen_examples/configs_nature/base.gin index a8593192..f704fa42 100644 --- a/infinigen_examples/configs_nature/base.gin +++ b/infinigen_examples/configs_nature/base.gin @@ -34,8 +34,7 @@ render_image.dof_aperture_fstop = 3 compositor_postprocessing.distort = False compositor_postprocessing.color_correct = False -flat/configure_render_cycles.min_samples = 1 -flat/configure_render_cycles.num_samples = 16 +flat/render_image.override_num_samples = 16 flat/render_image.flat_shading = True full/render_image.passes_to_save = [ ['diffuse_direct', 'DiffDir'], From 256c587d61719770f4b788895e0e7314d79021d7 Mon Sep 17 00:00:00 2001 From: Heather Doig Date: Thu, 5 Dec 2024 15:42:10 +1100 Subject: [PATCH 08/13] Update scene view in global_flat_shading() --- infinigen/core/rendering/render.py | 1 + 1 file changed, 1 insertion(+) diff --git a/infinigen/core/rendering/render.py b/infinigen/core/rendering/render.py index 8c970e24..ef07cf11 100644 --- a/infinigen/core/rendering/render.py +++ b/infinigen/core/rendering/render.py @@ -252,6 +252,7 @@ def global_flat_shading(): vol_socket = node.inputs["Volume"] if len(vol_socket.links) > 0: nw.links.remove(vol_socket.links[0]) + bpy.context.view_layer.update() for obj in bpy.context.scene.view_layers["ViewLayer"].objects: if obj.type != "MESH": From 2a95cd36308394723bff616ffad2f3d0b2bb30a3 Mon Sep 17 00:00:00 2001 From: Guangcheng Chen <31801020+GCChen97@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:06:52 +0800 Subject: [PATCH 09/13] replace diameter with radius in butil.spawn_capsule bmesh.ops.create_uvsphere requires radius instead of diameter in blender 3.6 --- infinigen/core/util/blender.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infinigen/core/util/blender.py b/infinigen/core/util/blender.py index 284329cd..45470694 100644 --- a/infinigen/core/util/blender.py +++ b/infinigen/core/util/blender.py @@ -510,7 +510,7 @@ def spawn_capsule(rad, height, us=32, vs=16): bpy.context.collection.objects.link(obj) bm = bmesh.new() - bmesh.ops.create_uvsphere(bm, u_segments=us, v_segments=vs, diameter=2 * rad) + bmesh.ops.create_uvsphere(bm, u_segments=us, v_segments=vs, radius=rad) for v in bm.verts: if v.co.z > 0: From d78670d954448532f150edc5c3e1804fd2d5472d Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Mon, 23 Dec 2024 16:25:30 +0000 Subject: [PATCH 10/13] Bugfix passthrough, add stdout_inline.gin pipeline config for singlejob logviewing --- infinigen/datagen/configs/stdout_inline.gin | 3 + infinigen/datagen/manage_jobs.py | 56 +++++++--- infinigen/datagen/util/submitit_emulator.py | 113 +++++++++++++++----- 3 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 infinigen/datagen/configs/stdout_inline.gin diff --git a/infinigen/datagen/configs/stdout_inline.gin b/infinigen/datagen/configs/stdout_inline.gin new file mode 100644 index 00000000..926f3490 --- /dev/null +++ b/infinigen/datagen/configs/stdout_inline.gin @@ -0,0 +1,3 @@ +LocalScheduleHandler.use_gpu = False +local_submit_cmd.stdout_passthrough = True +print_stats_block.mute = True \ No newline at end of file diff --git a/infinigen/datagen/manage_jobs.py b/infinigen/datagen/manage_jobs.py index 5363b9bf..9bef8200 100644 --- a/infinigen/datagen/manage_jobs.py +++ b/infinigen/datagen/manage_jobs.py @@ -184,11 +184,18 @@ def slurm_submit_cmd( @gin.configurable def local_submit_cmd( - cmd, folder: Path, name: str, use_scheduler=False, passthrough=False, **kwargs + cmd, + folder: Path, + name: str, + use_scheduler=False, + stdout_passthrough: bool = False, + **kwargs, ): ExecutorClass = ScheduledLocalExecutor if use_scheduler else ImmediateLocalExecutor - log_folder = (folder / "logs") if not passthrough else None - executor = ExecutorClass(folder=log_folder) + log_folder = folder / "logs" + log_folder.mkdir(exist_ok=True) + + executor = ExecutorClass(folder=log_folder, stdout_passthrough=stdout_passthrough) executor.update_parameters(name=name, **kwargs) if callable(cmd[0]): @@ -338,9 +345,15 @@ def update_symlink(scene_folder, scenes): to = scene_folder / "logs" / f"{new_name}.out" std_out = scene_folder / "logs" / f"{scene.job_id}_0_log.out" + if not std_out.exists(): + raise FileNotFoundError( + f"{std_out=} does not exist during attempt to symlink from {to=}" + ) + if os.path.islink(to): os.unlink(to) os.unlink(scene_folder / "logs" / f"{new_name}.err") + os.symlink(std_out.resolve(), to) os.symlink( std_out.with_suffix(".err").resolve(), @@ -704,6 +717,27 @@ def manage_datagen_jobs( return log_stats +@gin.configurable +def print_stats_block( + output_folder: Path, + start_time: datetime, + log_stats: dict, + mute: bool = False, +): + if mute: + return + + now = datetime.now() + + print( + f'{args.output_folder} {start_time.strftime("%m/%d %I:%M%p")} -> {now.strftime("%m/%d %I:%M%p")}' + ) + print("=" * 60) + for k, v in sorted(log_stats.items()): + print(f"{k.ljust(30)} : {v}") + print("-" * 60) + + @gin.configurable def main(args, shuffle=True, wandb_project="render", upload_commandfile_method=None): command_path = args.output_folder / "datagen_command.sh" @@ -752,25 +786,14 @@ def main(args, shuffle=True, wandb_project="render", upload_commandfile_method=N start_time = datetime.now() while any(j["all_done"] == SceneState.NotDone for j in all_scenes): - now = datetime.now() - - if args.print_stats: - print( - f'{args.output_folder} {start_time.strftime("%m/%d %I:%M%p")} -> {now.strftime("%m/%d %I:%M%p")}' - ) - log_stats = manage_datagen_jobs( - all_scenes, elapsed=(now - start_time).total_seconds() + all_scenes, elapsed=(datetime.now() - start_time).total_seconds() ) if wandb is not None: wandb.log(log_stats) - if args.print_stats: - print("=" * 60) - for k, v in sorted(log_stats.items()): - print(f"{k.ljust(30)} : {v}") - print("-" * 60) + print_stats_block(args.output_folder, start_time, log_stats) time.sleep(2) @@ -878,7 +901,6 @@ def main(args, shuffle=True, wandb_project="render", upload_commandfile_method=N parser.add_argument( "-v", "--verbose", action="store_const", dest="loglevel", const=logging.INFO ) - parser.add_argument("--print_stats", type=int, default=1) args = parser.parse_args() using_upload = any("upload" in x for x in args.pipeline_configs) diff --git a/infinigen/datagen/util/submitit_emulator.py b/infinigen/datagen/util/submitit_emulator.py index bd8bbafb..197e701f 100644 --- a/infinigen/datagen/util/submitit_emulator.py +++ b/infinigen/datagen/util/submitit_emulator.py @@ -13,7 +13,6 @@ import os import re import subprocess -from contextlib import nullcontext from dataclasses import dataclass from multiprocessing import Process from pathlib import Path @@ -60,6 +59,31 @@ def kill(self): self.process.kill() +class FileTee: + """ + Wrap a file-like object in order to write all its output to a stream aswell (usually sys.stdout or sys.stderr) + """ + + def __init__(self, inner, stream): + self.inner = inner + self.stream = stream + + def write(self, data): + self.inner.write(data) + self.stream.write(data) + + def flush(self): + self.inner.flush() + self.stream.flush() + + def close(self): + self.inner.close() + self.stream.close() + + def fileno(self): + return self.inner.fileno() + + def get_fake_job_id(): # Lahav assures me these will never conflict return np.random.randint(int(1e10), int(1e11)) @@ -67,13 +91,17 @@ def get_fake_job_id(): def job_wrapper( command: list[str], - stdout_file: Path = None, - stderr_file: Path = None, + stdout_file: Path, + stderr_file: Path, cuda_devices=None, + stdout_passthrough: bool = False, ): - stdout_ctx = stdout_file.open("w") if stdout_file is not None else nullcontext() - stderr_ctx = stderr_file.open("w") if stderr_file is not None else nullcontext() - with stdout_ctx as stdout, stderr_ctx as stderr: + with stdout_file.open("w") as stdout, stderr_file.open("w") as stderr: + if stdout_passthrough: + # TODO: send output to BOTH the file and the console + stdout = None + stderr = None + if cuda_devices is not None: env = os.environ.copy() env[CUDA_VARNAME] = ",".join([str(i) for i in cuda_devices]) @@ -82,31 +110,35 @@ def job_wrapper( subprocess.run( command, - stdout=stdout if stdout_file is not None else subprocess.PIPE, - stderr=stderr if stderr_file is not None else subprocess.PIPE, + stdout=stdout, + stderr=stderr, shell=False, check=False, # dont throw CalledProcessError env=env, ) -def launch_local(command: str, job_id, log_folder: Path, name: str, cuda_devices=None): - if log_folder is None: - # pass input through to stdout if log_folder is None - stderr_file = None - stdout_file = None - print(command) - else: - stderr_file = log_folder / f"{job_id}_0_log.err" - stdout_file = log_folder / f"{job_id}_0_log.out" - with stdout_file.open("w") as f: - f.write(f"{command}\n") +def launch_local( + command: str, + job_id: str, + log_folder: Path, + name: str, + cuda_devices=None, + stdout_passthrough: bool = False, +): + stderr_file = log_folder / f"{job_id}_0_log.err" + stdout_file = log_folder / f"{job_id}_0_log.out" + + with stdout_file.open("w") as f: + f.write(f"{command}\n") + stderr_file.touch() kwargs = dict( command=command, stdout_file=stdout_file, stderr_file=stderr_file, cuda_devices=cuda_devices, + stdout_passthrough=stdout_passthrough, ) proc = Process(target=job_wrapper, kwargs=kwargs, name=name) proc.start() @@ -115,12 +147,15 @@ def launch_local(command: str, job_id, log_folder: Path, name: str, cuda_devices class ImmediateLocalExecutor: - def __init__(self, folder: str | None): + def __init__(self, folder: str | None, stdout_passthrough: bool = False): if folder is None: self.log_folder = None else: self.log_folder = Path(folder).resolve() self.log_folder.mkdir(exist_ok=True) + + self.stdout_passthrough = stdout_passthrough + self.parameters = {} def update_parameters(self, **parameters): @@ -129,7 +164,13 @@ def update_parameters(self, **parameters): def submit(self, command: str): job_id = get_fake_job_id() name = self.parameters.get("name", None) - proc = launch_local(command, job_id, log_folder=self.log_folder, name=name) + proc = launch_local( + command, + job_id, + log_folder=self.log_folder, + name=name, + stdout_passthrough=self.stdout_passthrough, + ) return LocalJob(job_id=job_id, process=proc) @@ -148,7 +189,9 @@ def __init__(self, jobs_per_gpu=1, use_gpu=True): self.jobs_per_gpu = jobs_per_gpu self.use_gpu = use_gpu - def enqueue(self, command: str, params, log_folder): + def enqueue( + self, command: str, params: dict, log_folder: Path, stdout_passthrough: bool + ): job = LocalJob(job_id=get_fake_job_id(), process=None) job_rec = dict( command=command, @@ -156,8 +199,16 @@ def enqueue(self, command: str, params, log_folder): job=job, log_folder=log_folder, gpu_assignment=None, + stdout_passthrough=stdout_passthrough, ) + # matches behavior of submitit (?) - user code expects to be able to set up its + # symlinks for these logfiles right at job queue time + stderr_file = log_folder / f"{job.job_id}_0_log.err" + stdout_file = log_folder / f"{job.job_id}_0_log.out" + stderr_file.touch() + stdout_file.touch() + self.queue.append(job_rec) return job @@ -222,6 +273,7 @@ def dispatch(self, job_rec, resources): log_folder=job_rec["log_folder"], name=job_rec["params"].get("name", None), cuda_devices=gpu_idxs, + stdout_passthrough=job_rec["stdout_passthrough"], ) job_rec["gpu_assignment"] = gpu_assignment @@ -245,12 +297,12 @@ def attempt_dispatch_job( class ScheduledLocalExecutor: - def __init__(self, folder: str): - if folder is None: - self.log_folder = None - else: - self.log_folder = Path(folder) - self.log_folder.mkdir(exist_ok=True) + def __init__(self, folder: str, stdout_passthrough: bool = False): + self.log_folder = Path(folder) + self.log_folder.mkdir(exist_ok=True) + + self.stdout_passthrough = stdout_passthrough + self.parameters = {} def update_parameters(self, **parameters): @@ -258,7 +310,10 @@ def update_parameters(self, **parameters): def submit(self, command): return LocalScheduleHandler.instance().enqueue( - command, params=self.parameters, log_folder=self.log_folder + command, + params=self.parameters, + log_folder=self.log_folder, + stdout_passthrough=self.stdout_passthrough, ) From 20d7f150fac478f4d3657542ef638ba0ded5d3cd Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Mon, 23 Dec 2024 16:34:23 +0000 Subject: [PATCH 11/13] Bump version and changelog to v1.12.1 --- docs/CHANGELOG.md | 10 +++++++++- infinigen/__init__.py | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 105f85aa..bfd6a125 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -169,4 +169,12 @@ v1.11.4 - Improve success rate of camera / creature animations via increased retry attempts v1.12.0 -- Publish to PyPi \ No newline at end of file +- Publish to PyPi + +v1.12.1 +- Fix blender_gt crash from errored object in global_flat_shading +- Replace diameter with radius in butil.spawn_capsule +- Fix ignored blender_gt sample count config +- Fix outdated bbox input for camera_pose_proposal +- Bugfix stdout passthrough mode crashing due to no logfile created +- Add normalmaps to integration test viewer, misc test fixes diff --git a/infinigen/__init__.py b/infinigen/__init__.py index ed6df9fc..d1d7daf5 100644 --- a/infinigen/__init__.py +++ b/infinigen/__init__.py @@ -6,7 +6,7 @@ import logging from pathlib import Path -__version__ = "1.12.0" +__version__ = "1.12.1" def repo_root(): From 82727807d6d105377fe64d07929f1f08b75ce896 Mon Sep 17 00:00:00 2001 From: Alexander Raistrick Date: Mon, 23 Dec 2024 17:14:03 +0000 Subject: [PATCH 12/13] Avoid rare duplicate names in indoor solver --- docs/CHANGELOG.md | 1 + .../constraints/example_solver/propose_discrete.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index bfd6a125..ff054bb8 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -178,3 +178,4 @@ v1.12.1 - Fix outdated bbox input for camera_pose_proposal - Bugfix stdout passthrough mode crashing due to no logfile created - Add normalmaps to integration test viewer, misc test fixes +- Avoid rare duplicate names in indoor solver diff --git a/infinigen/core/constraints/example_solver/propose_discrete.py b/infinigen/core/constraints/example_solver/propose_discrete.py index 2b107d91..a2b52ba9 100644 --- a/infinigen/core/constraints/example_solver/propose_discrete.py +++ b/infinigen/core/constraints/example_solver/propose_discrete.py @@ -124,10 +124,15 @@ def propose_addition_bound_gen( for i, assignments in enumerate(all_assignments): logger.debug("Found assignments %d %s %s", i, len(assignments), assignments) + def sample_name(): + return f"{np.random.randint(1e6):04d}_{gen_class.__name__}" + + target_name = next( + sample_name() for _ in range(100) if sample_name() not in curr.objs + ) + yield moves.Addition( - names=[ - f"{np.random.randint(1e6):04d}_{gen_class.__name__}" - ], # decided later + names=[target_name], # decided later gen_class=gen_class, relation_assignments=assignments, temp_force_tags=prop_dom.tags, From 1b79a062ceadc53ccdf3b65d9a689866c9804a61 Mon Sep 17 00:00:00 2001 From: Vineet Bansal Date: Mon, 23 Dec 2024 15:43:51 -0500 Subject: [PATCH 13/13] added init.py files for some folders to act as submodules, to get gin to resolve *.gin paths for test_manage_jobs --- infinigen/datagen/configs/__init__.py | 0 infinigen/datagen/configs/compute_platform/__init__.py | 0 infinigen/datagen/configs/data_schema/__init__.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 infinigen/datagen/configs/__init__.py create mode 100644 infinigen/datagen/configs/compute_platform/__init__.py create mode 100644 infinigen/datagen/configs/data_schema/__init__.py diff --git a/infinigen/datagen/configs/__init__.py b/infinigen/datagen/configs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/infinigen/datagen/configs/compute_platform/__init__.py b/infinigen/datagen/configs/compute_platform/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/infinigen/datagen/configs/data_schema/__init__.py b/infinigen/datagen/configs/data_schema/__init__.py new file mode 100644 index 00000000..e69de29b