From 5cd8edebaa749c69cc0084318c66b34d0c46696d Mon Sep 17 00:00:00 2001 From: Robert LaThanh Date: Mon, 8 Jan 2024 16:18:47 -0800 Subject: [PATCH 1/4] Fix the ability to skip baseline sims in Docker-based implementations --- buildstockbatch/cloud/docker_base.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/buildstockbatch/cloud/docker_base.py b/buildstockbatch/cloud/docker_base.py index 35506226..ed280929 100644 --- a/buildstockbatch/cloud/docker_base.py +++ b/buildstockbatch/cloud/docker_base.py @@ -314,7 +314,10 @@ def _prep_jobs_for_batch(self, tmppath): self.validate_buildstock_csv(self.project_filename, df) building_ids = df.index.tolist() n_datapoints = len(building_ids) - n_sims = n_datapoints * (len(self.cfg.get("upgrades", [])) + 1) + if self.skip_baseline_sims: + n_sims = n_datapoints * len(self.cfg.get("upgrades", [])) + else: + n_sims = n_datapoints * (len(self.cfg.get("upgrades", [])) + 1) logger.debug("Total number of simulations = {}".format(n_sims)) # This is the maximum number of jobs that can be in an array @@ -327,9 +330,12 @@ def _prep_jobs_for_batch(self, tmppath): logger.debug("Number of simulations per array job = {}".format(n_sims_per_job)) # Create list of (building ID, upgrade to apply) pairs for all simulations to run. - baseline_sims = zip(building_ids, itertools.repeat(None)) upgrade_sims = itertools.product(building_ids, range(len(self.cfg.get("upgrades", [])))) - all_sims = list(itertools.chain(baseline_sims, upgrade_sims)) + if not self.skip_baseline_sims: + baseline_sims = zip(building_ids, itertools.repeat(None)) + all_sims = list(itertools.chain(baseline_sims, upgrade_sims)) + else: + all_sims = list(itertools.chain(upgrade_sims)) random.shuffle(all_sims) all_sims_iter = iter(all_sims) From 2327aa7b9e13e6108f142db6021f1c7e6f90a905 Mon Sep 17 00:00:00 2001 From: Robert LaThanh Date: Tue, 9 Jan 2024 13:51:14 -0800 Subject: [PATCH 2/4] Add test for skipping baseline sims --- buildstockbatch/test/test_docker_base.py | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/buildstockbatch/test/test_docker_base.py b/buildstockbatch/test/test_docker_base.py index d7194f92..1922cf60 100644 --- a/buildstockbatch/test/test_docker_base.py +++ b/buildstockbatch/test/test_docker_base.py @@ -18,6 +18,52 @@ resources_dir = os.path.join(here, "test_inputs", "test_openstudio_buildstock", "resources") +@docker_available +def test_skip_baseline_sims_false(basic_residential_project_file, mocker): + """Test that no "skip_sims" baseline configuration does not skip baseline sims.""" + project_filename, results_dir = basic_residential_project_file() + + mocker.patch.object(DockerBatchBase, "results_dir", results_dir) + sampler_property_mock = mocker.patch.object(DockerBatchBase, "sampler", new_callable=PropertyMock) + sampler_mock = mocker.MagicMock() + sampler_property_mock.return_value = sampler_mock + # Hard-coded sampling output includes 5 buildings. + sampler_mock.run_sampling = MagicMock(return_value=os.path.join(resources_dir, "buildstock_good.csv")) + + dbb = DockerBatchBase(project_filename) + dbb.batch_array_size = 3 + DockerBatchBase.validate_project = MagicMock(return_value=True) + + with tempfile.TemporaryDirectory(prefix="bsb_") as tmpdir: + _, batch_info = dbb._run_batch_prep(pathlib.Path(tmpdir)) + + assert batch_info.n_sims == 10 + + +@docker_available +def test_skip_baseline_sims_true(basic_residential_project_file, mocker): + """Test that ``skip_sims: true`` baseline configuration skips baseline sims.""" + project_filename, results_dir = basic_residential_project_file({"baseline": {"skip_sims": True}}) + + mocker.patch.object(DockerBatchBase, "results_dir", results_dir) + sampler_property_mock = mocker.patch.object(DockerBatchBase, "sampler", new_callable=PropertyMock) + sampler_mock = mocker.MagicMock() + sampler_property_mock.return_value = sampler_mock + # Hard-coded sampling output includes 5 buildings. + sampler_mock.run_sampling = MagicMock(return_value=os.path.join(resources_dir, "buildstock_good.csv")) + + dbb = DockerBatchBase(project_filename) + dbb.batch_array_size = 3 + DockerBatchBase.validate_project = MagicMock(return_value=True) + + print(f"dbb.skip_baseline_sims={dbb.skip_baseline_sims}") + + with tempfile.TemporaryDirectory(prefix="bsb_") as tmpdir: + _, batch_info = dbb._run_batch_prep(pathlib.Path(tmpdir)) + + assert batch_info.n_sims == 5 + + @docker_available def test_run_batch_prep(basic_residential_project_file, mocker): """Test that samples are created and bundled into batches correctly.""" From 375f050e3bb44d995dc79aba0d7e3b409253932d Mon Sep 17 00:00:00 2001 From: Robert LaThanh Date: Tue, 9 Jan 2024 13:53:11 -0800 Subject: [PATCH 3/4] Remove unnecessary step setting all_sims from upgrade_sims --- buildstockbatch/cloud/docker_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildstockbatch/cloud/docker_base.py b/buildstockbatch/cloud/docker_base.py index ed280929..25ceaef9 100644 --- a/buildstockbatch/cloud/docker_base.py +++ b/buildstockbatch/cloud/docker_base.py @@ -335,7 +335,7 @@ def _prep_jobs_for_batch(self, tmppath): baseline_sims = zip(building_ids, itertools.repeat(None)) all_sims = list(itertools.chain(baseline_sims, upgrade_sims)) else: - all_sims = list(itertools.chain(upgrade_sims)) + all_sims = list(upgrade_sims) random.shuffle(all_sims) all_sims_iter = iter(all_sims) From e4bf9b76fc323691543dc791cb078e9c4777130b Mon Sep 17 00:00:00 2001 From: Robert LaThanh Date: Wed, 10 Jan 2024 13:19:31 -0800 Subject: [PATCH 4/4] Parametrize test_skip_baseline_sims --- buildstockbatch/test/test_docker_base.py | 36 +++++------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/buildstockbatch/test/test_docker_base.py b/buildstockbatch/test/test_docker_base.py index 1922cf60..58799ec5 100644 --- a/buildstockbatch/test/test_docker_base.py +++ b/buildstockbatch/test/test_docker_base.py @@ -4,6 +4,7 @@ import json import os import pathlib +import pytest import shutil import tarfile import tempfile @@ -19,31 +20,11 @@ @docker_available -def test_skip_baseline_sims_false(basic_residential_project_file, mocker): - """Test that no "skip_sims" baseline configuration does not skip baseline sims.""" - project_filename, results_dir = basic_residential_project_file() - - mocker.patch.object(DockerBatchBase, "results_dir", results_dir) - sampler_property_mock = mocker.patch.object(DockerBatchBase, "sampler", new_callable=PropertyMock) - sampler_mock = mocker.MagicMock() - sampler_property_mock.return_value = sampler_mock - # Hard-coded sampling output includes 5 buildings. - sampler_mock.run_sampling = MagicMock(return_value=os.path.join(resources_dir, "buildstock_good.csv")) - - dbb = DockerBatchBase(project_filename) - dbb.batch_array_size = 3 - DockerBatchBase.validate_project = MagicMock(return_value=True) - - with tempfile.TemporaryDirectory(prefix="bsb_") as tmpdir: - _, batch_info = dbb._run_batch_prep(pathlib.Path(tmpdir)) - - assert batch_info.n_sims == 10 - - -@docker_available -def test_skip_baseline_sims_true(basic_residential_project_file, mocker): - """Test that ``skip_sims: true`` baseline configuration skips baseline sims.""" - project_filename, results_dir = basic_residential_project_file({"baseline": {"skip_sims": True}}) +@pytest.mark.parametrize("skip_baseline_sims,expected", [(False, 10), (True, 5)]) +def test_skip_baseline_sims(basic_residential_project_file, mocker, skip_baseline_sims, expected): + """Test "skip_sims" baseline configuration's effect on ``n_sims``""" + update_args = {"baseline": {"skip_sims": True}} if skip_baseline_sims else {} + project_filename, results_dir = basic_residential_project_file(update_args) mocker.patch.object(DockerBatchBase, "results_dir", results_dir) sampler_property_mock = mocker.patch.object(DockerBatchBase, "sampler", new_callable=PropertyMock) @@ -56,12 +37,9 @@ def test_skip_baseline_sims_true(basic_residential_project_file, mocker): dbb.batch_array_size = 3 DockerBatchBase.validate_project = MagicMock(return_value=True) - print(f"dbb.skip_baseline_sims={dbb.skip_baseline_sims}") - with tempfile.TemporaryDirectory(prefix="bsb_") as tmpdir: _, batch_info = dbb._run_batch_prep(pathlib.Path(tmpdir)) - - assert batch_info.n_sims == 5 + assert batch_info.n_sims == expected @docker_available