From b5b7724f2c0a929dd4894f3921878178c626366a Mon Sep 17 00:00:00 2001 From: John Harwell Date: Wed, 23 Oct 2024 13:18:42 -0500 Subject: [PATCH] refactor(#317): Better design - Get all ARgoS integration tests to pass again, and then cleanup static analysis --- noxfile.py | 9 +- scripts/argos-integration-tests.sh | 109 ++++++++++++++++-- scripts/core-integration-tests.sh | 10 +- scripts/ros1gazebo-integration-tests.sh | 42 ++++++- scripts/ros1robot-integration-tests.sh | 11 +- sierra/core/batchroot.py | 39 +++++-- sierra/core/exproot.py | 14 +-- sierra/core/pipeline/pipeline.py | 18 ++- sierra/core/pipeline/stage2/exp_runner.py | 9 +- sierra/core/pipeline/stage4/graphs/collate.py | 1 + .../pipeline/stage4/graphs/inter/generate.py | 2 +- .../pipeline/stage4/graphs/inter/heatmap.py | 2 +- .../core/pipeline/stage4/graphs/inter/line.py | 9 +- .../pipeline/stage4/graphs/intra/generate.py | 6 +- .../pipeline/stage4/graphs/intra/heatmap.py | 25 ++-- .../core/pipeline/stage4/graphs/intra/line.py | 14 +-- .../core/pipeline/stage4/pipeline_stage4.py | 9 +- .../stage5/inter_scenario_comparator.py | 2 +- .../stage5/intra_scenario_comparator.py | 67 +++++++---- sierra/core/pipeline/stage5/outputroot.py | 2 +- .../core/pipeline/stage5/pipeline_stage5.py | 21 ++-- sierra/core/variables/batch_criteria.py | 58 +++++++++- sierra/core/variables/population_size.py | 3 + sierra/core/variables/variable_density.py | 2 +- sierra/main.py | 1 + sierra/plugins/platform/argos/cmdline.py | 20 ++-- .../variables/population_constant_density.py | 2 + .../variables/population_variable_density.py | 4 +- .../ros1gazebo/variables/population_size.py | 4 +- 29 files changed, 379 insertions(+), 136 deletions(-) diff --git a/noxfile.py b/noxfile.py index 364660c1..3d687a28 100644 --- a/noxfile.py +++ b/noxfile.py @@ -63,7 +63,7 @@ def analyze_pytype(session): session.run('pytype', f'-j {cores}', '-k', - '-d name-error,attribute-error,invalid-annotation,pyi-error', + '-d name-error,attribute-error,pyi-error', 'sierra', external=True) @@ -74,8 +74,6 @@ def analyze_mypy(session): session.install('.') # same as 'pip3 install .' session.install('.[devel]') # same as 'pip3 install .[devel]' - cores = psutil.cpu_count() - session.run('mypyrun', '--select', # No syntax errors @@ -109,7 +107,10 @@ def analyze_mypy(session): 'name-match', 'no-untype-def', 'redundant-cast', - 'no-untyped-call' + 'disallow-untyped-calls', + 'check-untyped-defs', + 'disallow-untyped-defs', + 'disallow-incomplete-defs' # List types 'list-item', diff --git a/scripts/argos-integration-tests.sh b/scripts/argos-integration-tests.sh index 0de49ecc..9f55cd5a 100755 --- a/scripts/argos-integration-tests.sh +++ b/scripts/argos-integration-tests.sh @@ -27,7 +27,7 @@ setup_env() { # between jobs in a workflow on OSX, and doing this the way # github says to do doesn't work. export PATH=$pythonLocation/bin:$PATH - + # Required to get coverage.py to work with the installed version # of SIERRA. Omitting this results in either nothing getting # measured because the local site-packages is omitted, or if that @@ -186,7 +186,15 @@ bc_bivar_sanity_test() { # Check that stage 1 outputs what it is supposed to ################################################################################ stage1_univar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + batch_root=$(python3 -c "${batch_root_cmd}") input_root=$batch_root/exp-inputs/ rm -rf $SIERRA_ROOT @@ -219,11 +227,28 @@ stage1_univar_test() { } stage1_bivar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd1="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + batch_root_cmd2="from sierra.core import batchroot; +bc=[\"max_speed.1.9.C5\",\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + + batch_root1=$(python3 -c "${batch_root_cmd1}") input_root1=$batch_root1/exp-inputs/ - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"max_speed.1.9.C5\",\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root2=$(python3 -c"${batch_root_cmd2}") input_root2=$batch_root2/exp-inputs/ @@ -298,7 +323,16 @@ stage1_bivar_test() { # Check that stage 2 outputs what it is supposed to ################################################################################ stage2_univar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") output_root=$batch_root/exp-outputs/ scratch_root=$batch_root/scratch/ @@ -375,7 +409,15 @@ stage2_univar_check_outputs() { } stage2_bivar_test() { - batch_root1=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd1="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\", \"max_speed.1.9.C5\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + batch_root1=$(python3 -c"${batch_root_cmd1}") output_root1=$batch_root1/exp-outputs/ @@ -410,7 +452,15 @@ stage2_bivar_test() { # Check that stage 3 outputs what it is supposed to ################################################################################ stage3_univar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + batch_root=$(python3 -c"${batch_root_cmd}") stat_root=$batch_root/statistics rm -rf $SIERRA_ROOT @@ -460,7 +510,16 @@ stage3_univar_check_outputs() { } stage3_bivar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd1="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\", \"max_speed.1.9.C5\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd1}") output_root=$batch_root1/exp-outputs/ @@ -533,7 +592,15 @@ stage4_univar_test() { --physics-n-engines=1 \ --batch-criteria ${bc}\ --pipeline 1 2 3 4" - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"${bc}\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"${bc}\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + batch_root=$(python3 -c"${batch_root_cmd}") graph_root=$batch_root/graphs @@ -755,7 +822,16 @@ stage5_bivar_check_cc_outputs() { # Visual capture test ################################################################################ vc_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\", \"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") output_root=$batch_root/exp-outputs video_root=$batch_root/videos @@ -798,7 +874,16 @@ vc_test() { # Cmdline test ################################################################################ cmdline_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"argos_project\",[\"population_size.Linear3.C3\"],\"LowBlockCount.10x10x2\",\"foraging.footbot_foraging\",\"template\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"template\"; +scenario=\"LowBlockCount.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"argos_project\",controller=\"foraging.footbot_foraging\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") input_root=$batch_root/exp-inputs rm -rf $SIERRA_ROOT @@ -810,7 +895,7 @@ cmdline_test() { --exp-setup=exp_setup.T50" - $SIERRA_CMD --n-robots=10 --pipeline 1 + $SIERRA_CMD --n-agents=10 --pipeline 1 for exp in {0..2}; do for run in {0..3}; do diff --git a/scripts/core-integration-tests.sh b/scripts/core-integration-tests.sh index 9aa68a31..a5c6e09b 100755 --- a/scripts/core-integration-tests.sh +++ b/scripts/core-integration-tests.sh @@ -84,7 +84,15 @@ setup_env() { # Check usage of environment variables ################################################################################ env_vars_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"ros1robot_project\",[\"population_size.Linear3.C3\"],\"OutdoorWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"turtlebot3\"; +scenario=\"OutdoorWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1robot_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + batch_root=$(python3 -c"${batch_root_cmd}") input_root=$batch_root/exp-inputs/ rm -rf $SIERRA_ROOT diff --git a/scripts/ros1gazebo-integration-tests.sh b/scripts/ros1gazebo-integration-tests.sh index 46eb85fc..3779b9f8 100755 --- a/scripts/ros1gazebo-integration-tests.sh +++ b/scripts/ros1gazebo-integration-tests.sh @@ -93,7 +93,16 @@ bc_bivar_sanity_test() { # Check that stage 1 outputs what it is supposed to ################################################################################ stage1_univar_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"ros1gazebo_project\",[\"population_size.Linear3.C3\"],\"HouseWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3_house\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"turtlebot3_house\"; +scenario=\"HouseWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1gazebo_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") input_root=$batch_root/exp-inputs/ rm -rf $SIERRA_ROOT @@ -125,11 +134,27 @@ stage1_univar_test() { } stage1_bivar_test() { - batch_root1=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"ros1gazebo_project\",[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"],\"HouseWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3_house\").to_path())") + batch_root_cmd1="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\",\"max_speed.1.9.C5\"]; +template_stem=\"turtlebot3_house\"; +scenario=\"HouseWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1gazebo_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + batch_root_cmd2="from sierra.core import batchroot; +bc=[\"max_speed.1.9.C5\",\"population_size.Linear3.C3\"]; +template_stem=\"turtlebot3_house\"; +scenario=\"HouseWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1gazebo_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + batch_root1=$(python3 -c"${batch_root_cmd1}") input_root1=$batch_root1/exp-inputs/ - batch_root1=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"ros1gazebo_project\",[\"max_speed.1.9.C5\",\"population_size.Linear3.C3\"],\"HouseWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3_house\").to_path())") + batch_root2=$(python3 -c"${batch_root_cmd2}") input_root2=$batch_root2/exp-inputs/ @@ -197,7 +222,16 @@ stage1_bivar_test() { # Check that stage 2 works for all exec envs ################################################################################ stage2_univar_test() { - batch_root=$(python3 -c"import sierra.core.root_dirpath_generator as rdg;print(rdg.gen_batch_root(\"$SIERRA_ROOT\",\"ros1gazebo_project\",[\"population_size.Linear3.C3\"],\"HouseWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3_house\"))") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"turtlebot3_house\"; +scenario=\"HouseWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1gazebo_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") scratch_root=$batch_root/scratch/ diff --git a/scripts/ros1robot-integration-tests.sh b/scripts/ros1robot-integration-tests.sh index 3d2c4af7..eddba21a 100755 --- a/scripts/ros1robot-integration-tests.sh +++ b/scripts/ros1robot-integration-tests.sh @@ -77,7 +77,16 @@ bc_univar_sanity_test() { # Check that stage 1 outputs what it is supposed to ################################################################################ stage1_test() { - batch_root=$(python3 -c"from sierra.core.batchroot import batchroot;print(batchroot.ExpRoot(\"$SIERRA_ROOT\",\"ros1gazebo_project\",[\"population_size.Linear3.C3\"],\"OutdoorWorld.10x10x2\",\"turtlebot3.wander\", \"turtlebot3\").to_path())") + batch_root_cmd="from sierra.core import batchroot; +bc=[\"population_size.Linear3.C3\"]; +template_stem=\"turtlebot3\"; +scenario=\"OutdoorWorld.10x10x2\"; +leaf=batchroot.ExpRootLeaf(bc=bc,template_stem=template_stem,scenario=scenario); +path=batchroot.ExpRoot(sierra_root=\"$SIERRA_ROOT\",project=\"ros1robot_project\",controller=\"turtlebot3.wander\",leaf=leaf).to_path(); +print(path) +" + + batch_root=$(python3 -c"${batch_root_cmd}") input_root=$batch_root/exp-inputs/ rm -rf $SIERRA_ROOT diff --git a/sierra/core/batchroot.py b/sierra/core/batchroot.py index d5640904..1a6102a7 100644 --- a/sierra/core/batchroot.py +++ b/sierra/core/batchroot.py @@ -39,7 +39,8 @@ def from_components(bc: tp.List[str], scenario: str) -> 'ExpRootLeaf': return ExpRootLeaf(bc, template_stem, scenario) - def __init__(self, bc: tp.List[str], + def __init__(self, + bc: tp.List[str], template_stem: str, scenario: str) -> None: self.bc = bc @@ -47,12 +48,16 @@ def __init__(self, bc: tp.List[str], self.scenario = scenario def to_path(self) -> pathlib.Path: - root = pathlib.Path(f"{0}-{1}+{2}" % (self.template_stem, - self.scenario, - '+'.join(self.bc))) - logging.debug("Generated batch leaf %s", root) + root = pathlib.Path("{0}-{1}+{2}".format( + self.template_stem, + self.scenario, + '+'.join(self.bc))) + logging.trace("Generated batch leaf %s", root.as_posix()) return root + def to_str(self) -> str: + return str(self.to_path()) + class ExpRoot(): def __init__(self, @@ -91,6 +96,9 @@ def __init__(self, def to_path(self) -> pathlib.Path: return self.sierra_root / self.project / self.controller / self.leaf.to_path() + def to_str(self) -> str: + return str(self.to_path()) + class PathSet(): def __init__(self, root: ExpRoot) -> None: @@ -99,14 +107,27 @@ def __init__(self, root: ExpRoot) -> None: self.graph_root = root.to_path() / "graphs" self.model_root = root.to_path() / "models" self.stat_root = root.to_path() / "statistics" - self.stat_exec_root = self.stat_root.to_path() / "exec" + self.stat_exec_root = self.stat_root / "exec" self.imagize_root = root.to_path() / "imagize" self.video_root = root.to_path() / "videos" - self.stat_collate_root = self.stat_root.to_path() / "collated" - self.graph_collate_root = self.graph_root.to_path() / "collated" + self.stat_collate_root = self.stat_root / "collated" + self.graph_collate_root = self.graph_root / "collated" self.scratch_root = root.to_path() / "scratch" self.root = root.to_path() + def __str__(self) -> str: + return (f"Batch root: {self.root}\n" + + f"Input root: /{self.input_root.name}\n" + + f"Output root: /{self.output_root.name}\n" + + f"Graph root: /{self.graph_root.name}\n" + + f"Model root: /{self.model_root.name}\n" + + f"Statistics root: /{self.stat_root.name}\n" + + f"Execution statistics root: /{self.stat_exec_root.name}\n" + + f"Imagizing root: /{self.imagize_root.name}\n" + + f"Video root: /{self.video_root.name}\n" + + f"Statistics collate root: /{self.stat_collate_root.name}\n" + + f"Experiment scratch root: /{self.scratch_root.name}") + def from_cmdline(args: argparse.Namespace) -> PathSet: """Generate directory paths directly from cmdline arguments. @@ -154,5 +175,5 @@ def from_exp(sierra_root: str, project, controller, batch_leaf) - logging.info('Generated batch root %s', root) + logging.info('Generated batch root %s', root.to_path()) return PathSet(root) diff --git a/sierra/core/exproot.py b/sierra/core/exproot.py index 305f724b..a04a911c 100644 --- a/sierra/core/exproot.py +++ b/sierra/core/exproot.py @@ -18,12 +18,12 @@ def __init__(self, batch: batchroot.PathSet, exp_name: str, exp0_name: tp.Optional[str] = None) -> None: - self.input_root = batch.input_root.to_path() / exp_name - self.output_root = batch.output_root.to_path() / exp_name - self.graph_root = batch.graph_root.to_path() / exp_name - self.model_root = batch.model_root.to_path() / exp_name - self.stat_root = batch.state_root.to_path() / exp_name + self.input_root = batch.input_root / exp_name + self.output_root = batch.output_root / exp_name + self.graph_root = batch.graph_root / exp_name + self.model_root = batch.model_root / exp_name + self.stat_root = batch.stat_root / exp_name if exp0_name: - self.exp0_output_root = batch.output_root.to_path() / exp0_name - self.exp0_stat_root = batch.stat_root.to_path() / exp0_name + self.exp0_output_root = batch.output_root / exp0_name + self.exp0_stat_root = batch.stat_root / exp0_name diff --git a/sierra/core/pipeline/pipeline.py b/sierra/core/pipeline/pipeline.py index 3aa5cc73..e93c0167 100755 --- a/sierra/core/pipeline/pipeline.py +++ b/sierra/core/pipeline/pipeline.py @@ -18,7 +18,7 @@ # Project packages import sierra.core.plugin_manager as pm -from sierra.core import types, config, utils, batchroot +from sierra.core import config, utils, batchroot from sierra.core.pipeline.stage1.pipeline_stage1 import PipelineStage1 from sierra.core.pipeline.stage2.pipeline_stage2 import PipelineStage2 @@ -36,6 +36,9 @@ def __init__(self, pathset: tp.Optional[batchroot.PathSet] = None) -> None: self.args = args self.logger = logging.getLogger(__name__) + self.pathset = pathset + + self.logger.trace("%s", self.pathset) assert all(stage in [1, 2, 3, 4, 5] for stage in args.pipeline), \ f"Invalid pipeline stage in {args.pipeline}: Only 1-5 valid" @@ -106,7 +109,7 @@ def __init__(self, platform=self.cmdopts['platform']) module.PlatformCmdline.cmdopts_update(self.args, self.cmdopts) - if pathset is not None: + if self.pathset is not None: # Load additional cmdline options from project. This is mandatory, # because all projects have to define --controller and --scenario # at a minimum. @@ -131,6 +134,7 @@ def __init__(self, path='variables.batch_criteria') self.batch_criteria = bc.factory(self.main_config, self.cmdopts, + self.pathset.input_root, self.args) self.controller = controller @@ -141,19 +145,23 @@ def run(self) -> None: """ if 1 in self.args.pipeline: PipelineStage1(self.cmdopts, + self.pathset, self.controller, # type: ignore self.batch_criteria).run() if 2 in self.args.pipeline: - PipelineStage2(self.cmdopts, self.pathset).run(self.batch_criteria) + PipelineStage2(self.cmdopts, + self.pathset).run(self.batch_criteria) if 3 in self.args.pipeline: PipelineStage3(self.main_config, - self.cmdopts, self.pathset).run(self.batch_criteria) + self.cmdopts, + self.pathset).run(self.batch_criteria) if 4 in self.args.pipeline: PipelineStage4(self.main_config, - self.cmdopts).run(self.batch_criteria) + self.cmdopts, + self.pathset).run(self.batch_criteria) # not part of default pipeline if 5 in self.args.pipeline: diff --git a/sierra/core/pipeline/stage2/exp_runner.py b/sierra/core/pipeline/stage2/exp_runner.py index 733bb663..0eb18b4b 100755 --- a/sierra/core/pipeline/stage2/exp_runner.py +++ b/sierra/core/pipeline/stage2/exp_runner.py @@ -13,6 +13,7 @@ import datetime import logging import pathlib +import typing as tp # 3rd party packages @@ -162,13 +163,15 @@ def __call__(self) -> None: # Output some useful information before running if hasattr(module, 'pre_exp_diagnostics'): - module.pre_exp_diagnostics(self.cmdopts, self.logger) + module.pre_exp_diagnostics(self.cmdopts, + self.pathset, + self.logger) - exp_all = [self.batch_exp_root / d + exp_all = [self.pathset.input_root / d for d in self.criteria.gen_exp_names()] exp_to_run = utils.exp_range_calc(self.cmdopts["exp_range"], - self.batch_exp_root, + self.pathset.input_root, self.criteria) # Verify environment is OK before running anything diff --git a/sierra/core/pipeline/stage4/graphs/collate.py b/sierra/core/pipeline/stage4/graphs/collate.py index 839d3d11..c235a3f3 100755 --- a/sierra/core/pipeline/stage4/graphs/collate.py +++ b/sierra/core/pipeline/stage4/graphs/collate.py @@ -261,6 +261,7 @@ def __init__(self, pathset: batchroot.PathSet) -> None: self.main_config = main_config self.cmdopts = cmdopts + self.pathset = pathset utils.dir_create_checked(pathset.stat_collate_root, exist_ok=True) diff --git a/sierra/core/pipeline/stage4/graphs/inter/generate.py b/sierra/core/pipeline/stage4/graphs/inter/generate.py index 89938a11..12e161a5 100755 --- a/sierra/core/pipeline/stage4/graphs/inter/generate.py +++ b/sierra/core/pipeline/stage4/graphs/inter/generate.py @@ -20,8 +20,8 @@ def generate(main_config: types.YAMLDict, - pathset: batchroot.PathSet, cmdopts: types.Cmdopts, + pathset: batchroot.PathSet, LN_targets: tp.List[types.YAMLDict], HM_targets: tp.List[types.YAMLDict], criteria: bc.IConcreteBatchCriteria) -> None: diff --git a/sierra/core/pipeline/stage4/graphs/inter/heatmap.py b/sierra/core/pipeline/stage4/graphs/inter/heatmap.py index 3b99083b..d0acacd6 100644 --- a/sierra/core/pipeline/stage4/graphs/inter/heatmap.py +++ b/sierra/core/pipeline/stage4/graphs/inter/heatmap.py @@ -66,7 +66,7 @@ def _generate_hm(graph: types.YAMLDict, interval: int, ipath: pathlib.Path) -> None: - odir = graph_root / ("HM-" + graph['dest_stem']) + odir = graph_collate_root / ("HM-" + graph['dest_stem']) odir.mkdir(parents=True, exist_ok=True) opath = odir / ('HM-{0}_{1}{2}'.format(graph['dest_stem'], interval, diff --git a/sierra/core/pipeline/stage4/graphs/inter/line.py b/sierra/core/pipeline/stage4/graphs/inter/line.py index 9fbb29e9..c6fcd49f 100644 --- a/sierra/core/pipeline/stage4/graphs/inter/line.py +++ b/sierra/core/pipeline/stage4/graphs/inter/line.py @@ -56,8 +56,8 @@ def _gen_summary_linegraph(graph: types.YAMLDict, pathset: batchroot.PathSet, cmdopts: types.Cmdopts, criteria: bc.IConcreteBatchCriteria) -> None: - opath = pathset.graph_root / ('SM-' + graph['dest_stem'] + config.kImageExt) - + opath = pathset.graph_collate_root / \ + ('SM-' + graph['dest_stem'] + config.kImageExt) ln = SummaryLineGraph(stats_root=pathset.stat_collate_root, input_stem=graph['dest_stem'], output_fpath=opath, @@ -79,9 +79,8 @@ def _gen_stacked_linegraph(graph: types.YAMLDict, pathset: batchroot.PathSet, cmdopts: types.Cmdopts, criteria: bc.IConcreteBatchCriteria) -> None: - opath = pathset.graph_root / ('SLN-' + graph['dest_stem'] + - config.kImageExt) - + opath = pathset.graph_collate_root / ('SLN-' + graph['dest_stem'] + + config.kImageExt) ln = StackedLineGraph(stats_root=pathset.stat_collate_root, input_stem=graph['dest_stem'], output_fpath=opath, diff --git a/sierra/core/pipeline/stage4/graphs/intra/generate.py b/sierra/core/pipeline/stage4/graphs/intra/generate.py index 783c7b70..75e8c816 100755 --- a/sierra/core/pipeline/stage4/graphs/intra/generate.py +++ b/sierra/core/pipeline/stage4/graphs/intra/generate.py @@ -142,15 +142,15 @@ def __call__(self, #. :func:`~sierra.core.pipeline.stage4.graphs.intra.heatmap.generate()` to generate heatmaps for each experiment in the batch. """ - utils.dir_create_checked(self.pathset.graph_root, exist_ok=True) + utils.dir_create_checked(pathset.graph_root, exist_ok=True) LN_targets, HM_targets = self.calc_targets() if not self.cmdopts['project_no_LN']: - line.generate(self.cmdopts, LN_targets) + line.generate(self.cmdopts, pathset, LN_targets) if not self.cmdopts['project_no_HM']: - heatmap.generate(self.cmdopts, HM_targets) + heatmap.generate(self.cmdopts, pathset, HM_targets) def calc_targets(self) -> tp.Tuple[tp.List[types.YAMLDict], tp.List[types.YAMLDict]]: diff --git a/sierra/core/pipeline/stage4/graphs/intra/heatmap.py b/sierra/core/pipeline/stage4/graphs/intra/heatmap.py index 16517258..27cbf347 100644 --- a/sierra/core/pipeline/stage4/graphs/intra/heatmap.py +++ b/sierra/core/pipeline/stage4/graphs/intra/heatmap.py @@ -6,14 +6,13 @@ # Core packages import typing as tp -import pathlib import logging # 3rd party packages import json # Project packages -from sierra.core import types, config +from sierra.core import types, config, exproot from sierra.core.models.graphs import IntraExpModel2DGraphSet from sierra.core.graphs.heatmap import Heatmap @@ -21,18 +20,16 @@ def generate(cmdopts: types.Cmdopts, + pathset: exproot.PathSet, targets: tp.List[types.YAMLDict]) -> None: """ Generate heatmaps from: term: `Averaged .csv` files for a single experiment. """ - exp_stat_root = pathlib.Path(cmdopts['exp_stat_root']) - exp_graph_root = pathlib.Path(cmdopts["exp_graph_root"]) - exp_model_root = pathlib.Path(cmdopts["exp_model_root"]) large_text = cmdopts['plot_large_text'] targets = targets - _logger.info("Heatmaps from %s", exp_stat_root) + _logger.info("Heatmaps from %s", pathset.stat_root) # For each category of heatmaps we are generating for category in targets: @@ -41,18 +38,18 @@ def generate(cmdopts: types.Cmdopts, for graph in category['graphs']: _logger.trace('\n' + # type: ignore json.dumps(graph, indent=4)) - if IntraExpModel2DGraphSet.model_exists(exp_model_root, + if IntraExpModel2DGraphSet.model_exists(pathset.model_root, graph['src_stem']): - IntraExpModel2DGraphSet(exp_stat_root, - exp_model_root, - exp_graph_root, + IntraExpModel2DGraphSet(pathset.stat_root, + pathset.model_root, + pathset.graph_root, graph['src_stem'], graph.get('title', None)).generate() else: - input_fpath = exp_stat_root / (graph['src_stem'] + - config.kStats['mean'].exts['mean']) - output_fpath = exp_graph_root / ('HM-' + graph['src_stem'] + - config.kImageExt) + input_fpath = pathset.stat_root / (graph['src_stem'] + + config.kStats['mean'].exts['mean']) + output_fpath = pathset.graph_root / ('HM-' + graph['src_stem'] + + config.kImageExt) Heatmap(input_fpath=input_fpath, output_fpath=output_fpath, diff --git a/sierra/core/pipeline/stage4/graphs/intra/line.py b/sierra/core/pipeline/stage4/graphs/intra/line.py index 380772b3..5a0b4f62 100644 --- a/sierra/core/pipeline/stage4/graphs/intra/line.py +++ b/sierra/core/pipeline/stage4/graphs/intra/line.py @@ -5,7 +5,6 @@ # # Core packages -import pathlib import typing as tp import logging @@ -13,33 +12,32 @@ import json # Project packages -from sierra.core import types, config +from sierra.core import types, config, exproot from sierra.core.graphs.stacked_line_graph import StackedLineGraph _logger = logging.getLogger(__name__) def generate(cmdopts: types.Cmdopts, + pathset: exproot.PathSet, targets: tp.List[types.YAMLDict]) -> None: """ Generate linegraphs from: term: `Averaged .csv` files within an experiment. """ - graph_root = pathlib.Path(cmdopts['exp_graph_root']) - stats_root = pathlib.Path(cmdopts['exp_stat_root']) - _logger.info("Linegraphs from %s", cmdopts['exp_stat_root']) + _logger.info("Linegraphs from %s", pathset.stat_root) # For each category of linegraphs we are generating for category in targets: # For each graph in each category for graph in category['graphs']: - output_fpath = graph_root / ('SLN-' + graph['dest_stem'] + - config.kImageExt) + output_fpath = pathset.graph_root / ('SLN-' + graph['dest_stem'] + + config.kImageExt) try: _logger.trace('\n' + # type: ignore json.dumps(graph, indent=4)) - StackedLineGraph(stats_root=stats_root, + StackedLineGraph(stats_root=pathset.stat_root, input_stem=graph['src_stem'], output_fpath=output_fpath, stats=cmdopts['dist_stats'], diff --git a/sierra/core/pipeline/stage4/pipeline_stage4.py b/sierra/core/pipeline/stage4/pipeline_stage4.py index a097d534..897ad56c 100755 --- a/sierra/core/pipeline/stage4/pipeline_stage4.py +++ b/sierra/core/pipeline/stage4/pipeline_stage4.py @@ -24,7 +24,7 @@ from sierra.core.pipeline.stage4 import render import sierra.core.plugin_manager as pm -from sierra.core import types, config, utils +from sierra.core import types, config, utils, batchroot class PipelineStage4: @@ -89,9 +89,11 @@ class PipelineStage4: def __init__(self, main_config: types.YAMLDict, - cmdopts: types.Cmdopts) -> None: - self.cmdopts = cmdopts + cmdopts: types.Cmdopts, + pathset: batchroot.PathSet) -> None: self.main_config = main_config + self.cmdopts = cmdopts + self.pathset = pathset self.project_config_root = pathlib.Path(self.cmdopts['project_config_root']) controllers_yaml = self.project_config_root / config.kYAML.controllers @@ -406,6 +408,7 @@ def _run_inter_graph_generation(self, criteria: bc.IConcreteBatchCriteria) -> No path='pipeline.stage4.graphs.inter.generate') module.generate(self.main_config, self.cmdopts, + self.pathset, LN_targets, HM_targets, criteria) diff --git a/sierra/core/pipeline/stage5/inter_scenario_comparator.py b/sierra/core/pipeline/stage5/inter_scenario_comparator.py index ab02b43b..6c2536d8 100755 --- a/sierra/core/pipeline/stage5/inter_scenario_comparator.py +++ b/sierra/core/pipeline/stage5/inter_scenario_comparator.py @@ -129,7 +129,7 @@ def _leaf_select(self, candidate: str) -> bool: """ leaf = batchroot.ExpRootLeaf.from_name(candidate) - return leaf.to_path() in candidate and leaf.scenario in self.scenarios + return leaf.to_str() in candidate and leaf.scenario in self.scenarios def _compare_across_scenarios(self, cmdopts: types.Cmdopts, diff --git a/sierra/core/pipeline/stage5/intra_scenario_comparator.py b/sierra/core/pipeline/stage5/intra_scenario_comparator.py index d4393bd9..83e7a5cf 100755 --- a/sierra/core/pipeline/stage5/intra_scenario_comparator.py +++ b/sierra/core/pipeline/stage5/intra_scenario_comparator.py @@ -114,7 +114,7 @@ def _leaf_select(self, candidate: str) -> bool: """ leaf = batchroot.ExpRootLeaf.from_name(candidate).to_path() - return leaf in candidate + return str(leaf) in candidate def _compare_in_scenario(self, cmdopts: types.Cmdopts, @@ -124,7 +124,8 @@ def _compare_in_scenario(self, for controller in self.controllers: dirs = [d for d in os.listdir( - self.project_root / controller) if batch_leaf in d] + self.project_root / controller) if batch_leaf.to_str() in d] + if len(dirs) == 0: self.logger.warning("Controller %s was not run on experiment %s", controller, @@ -198,7 +199,7 @@ def _gen_csv(self, ipath_leaf=src_stem, opath_stem=self.stage5_roots.csv_root, n_exp=criteria.n_exp()) - opath_leaf = namecalc.for_output(batch_leaf.name, dest_stem, None) + opath_leaf = namecalc.for_output(batch_leaf, dest_stem, None) preparer.across_rows(opath_leaf=opath_leaf, index=0, inc_exps=inc_exps) def _gen_graph(self, @@ -324,8 +325,8 @@ def _leaf_select(self, candidate: str) -> bool: cause file not found errors. """ - leaf = batchroot.ExpRootLeaf.from_name(candidate).to_path() - return leaf in candidate + leaf = batchroot.ExpRootLeaf.from_name(candidate) + return leaf.to_str() in candidate def _compare_in_scenario(self, cmdopts: types.Cmdopts, @@ -339,7 +340,7 @@ def _compare_in_scenario(self, """ for controller in self.controllers: dirs = [d for d in os.listdir( - self.project_root / controller) if batch_leaf in d] + self.project_root / controller) if batch_leaf.to_str() in d] if len(dirs) == 0: self.logger.warning("Controller '%s' was not run on scenario '%s'", @@ -398,6 +399,7 @@ def _compare_in_scenario(self, self._gen_graphs2D(batch_leaf=batch_leaf, criteria=criteria, cmdopts=cmdopts, + batch_output_root=pathset.output_root, dest_stem=graph['dest_stem'], title=graph.get('title', ''), label=graph.get('label', ''), @@ -408,6 +410,7 @@ def _compare_in_scenario(self, self._gen_graph3D(batch_leaf=batch_leaf, criteria=criteria, cmdopts=cmdopts, + batch_output_root=pathset.output_root, dest_stem=graph['dest_stem'], title=graph.get('title', ''), zlabel=graph.get('label', ''), @@ -485,7 +488,7 @@ def _gen_csvs_for_1D(self, controller, src_stem, dest_stem) csv_ipath = pathset.stat_collate_root / \ - src_stem + config.kStats['mean'].exts['mean'] + (src_stem + config.kStats['mean'].exts['mean']) # Some experiments might not generate the necessary performance measure # .csvs for graph generation, which is OK. @@ -566,24 +569,26 @@ def _gen_graphs1D(self, if primary_axis == 0: n_exp = criteria.criteria1.n_exp() - xticks = utils.exp_include_filter(inc_exps, - criteria.graph_yticks( - cmdopts), - n_exp) + yticks = criteria.graph_yticks(cmdopts, + pathset.output_root) + xticks = utils.exp_include_filter(inc_exps, yticks, n_exp) + + ytick_labels = criteria.graph_yticklabels(cmdopts, + pathset.output_root) xtick_labels = utils.exp_include_filter(inc_exps, - criteria.graph_yticklabels( - cmdopts), + ytick_labels, n_exp) xlabel = criteria.graph_ylabel(cmdopts) else: n_exp = criteria.criteria2.n_exp() - xticks = utils.exp_include_filter(inc_exps, - criteria.graph_xticks( - cmdopts), - n_exp) + yticks = criteria.graph_xticks(cmdopts, + pathset.output_root) + xticks = utils.exp_include_filter(inc_exps, yticks, n_exp) + + ytick_labels = criteria.graph_xticklabels(cmdopts, + pathset.output_root) xtick_labels = utils.exp_include_filter(inc_exps, - criteria.graph_xticklabels( - cmdopts), + ytick_labels, n_exp) xlabel = criteria.graph_xlabel(cmdopts) @@ -606,6 +611,7 @@ def _gen_graphs2D(self, batch_leaf: batchroot.ExpRootLeaf, criteria: bc.BivarBatchCriteria, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, dest_stem: str, title: str, label: str, @@ -615,6 +621,7 @@ def _gen_graphs2D(self, self._gen_paired_heatmaps(batch_leaf, criteria, cmdopts, + batch_output_root, dest_stem, title, label, @@ -623,6 +630,7 @@ def _gen_graphs2D(self, self._gen_dual_heatmaps(batch_leaf, criteria, cmdopts, + batch_output_root, dest_stem, title, label, @@ -633,6 +641,7 @@ def _gen_paired_heatmaps(self, batch_leaf: batchroot.ExpRootLeaf, criteria: bc.BivarBatchCriteria, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, dest_stem: str, title: str, label: str, @@ -694,13 +703,16 @@ def _gen_paired_heatmaps(self, zlabel=self._gen_zaxis_label(label, comp_type), xlabel=criteria.graph_xlabel(cmdopts), ylabel=criteria.graph_ylabel(cmdopts), - xtick_labels=criteria.graph_xticklabels(cmdopts), - ytick_labels=criteria.graph_yticklabels(cmdopts)).generate() + xtick_labels=criteria.graph_xticklabels(cmdopts, + batch_output_root), + ytick_labels=criteria.graph_yticklabels(cmdopts, + batch_output_root)).generate() def _gen_dual_heatmaps(self, batch_leaf: batchroot.ExpRootLeaf, criteria: bc.BivarBatchCriteria, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, dest_stem: str, title: str, label: str, @@ -736,13 +748,16 @@ def _gen_dual_heatmaps(self, xlabel=criteria.graph_xlabel(cmdopts), ylabel=criteria.graph_ylabel(cmdopts), legend=legend, - xtick_labels=criteria.graph_xticklabels(cmdopts), - ytick_labels=criteria.graph_yticklabels(cmdopts)).generate() + xtick_labels=criteria.graph_xticklabels(cmdopts, + batch_output_root), + ytick_labels=criteria.graph_yticklabels(cmdopts, + batch_output_root)).generate() def _gen_graph3D(self, batch_leaf: batchroot.ExpRootLeaf, criteria: bc.BivarBatchCriteria, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, dest_stem: str, title: str, zlabel: str, @@ -775,8 +790,10 @@ def _gen_graph3D(self, ylabel=criteria.graph_xlabel(cmdopts), xlabel=criteria.graph_ylabel(cmdopts), zlabel=self._gen_zaxis_label(zlabel, comp_type), - xtick_labels=criteria.graph_yticklabels(cmdopts), - ytick_labels=criteria.graph_xticklabels(cmdopts), + xtick_labels=criteria.graph_yticklabels(cmdopts, + batch_output_root), + ytick_labels=criteria.graph_xticklabels(cmdopts, + batch_output_root), legend=legend, comp_type=comp_type).generate() diff --git a/sierra/core/pipeline/stage5/outputroot.py b/sierra/core/pipeline/stage5/outputroot.py index 4637e944..fdbc06b8 100644 --- a/sierra/core/pipeline/stage5/outputroot.py +++ b/sierra/core/pipeline/stage5/outputroot.py @@ -28,7 +28,7 @@ def __init__(self, if controllers: self.graph_root = pathlib.Path(cmdopts['sierra_root'], cmdopts['project'], - '+'.join(controllers) + "-cc-graphs"), + '+'.join(controllers) + "-cc-graphs") self.csv_root = pathlib.Path(cmdopts['sierra_root'], cmdopts['project'], diff --git a/sierra/core/pipeline/stage5/pipeline_stage5.py b/sierra/core/pipeline/stage5/pipeline_stage5.py index b70ffd4b..61341c47 100755 --- a/sierra/core/pipeline/stage5/pipeline_stage5.py +++ b/sierra/core/pipeline/stage5/pipeline_stage5.py @@ -9,6 +9,8 @@ # Core packages import logging import pathlib +import typing as tp +import argparse # 3rd party packages import yaml @@ -18,6 +20,7 @@ from sierra.core.pipeline.stage5 import inter_scenario_comparator as intersc from sierra.core.pipeline.stage5 import outputroot from sierra.core import types, utils, config, batchroot +from sierra.core.generators.controller_generator_parser import ControllerGeneratorParser class PipelineStage5: @@ -81,7 +84,7 @@ def __init__(self, self.project_root = pathlib.Path(self.cmdopts['sierra_root'], self.cmdopts['project']) - def run(self, cli_args) -> None: + def run(self, cli_args: argparse.Namespace) -> None: """Run stage 5 of the experimental pipeline. If ``--controller-comparison`` was passed: @@ -111,7 +114,7 @@ def run(self, cli_args) -> None: elif self.cmdopts['scenario_comparison']: self._run_sc(cli_args) - def _run_cc(self, cli_args): + def _run_cc(self, cli_args: argparse.Namespace) -> None: # Use nice controller names on graph legends if configured if self.cmdopts['controllers_legend'] is not None: legend = self.cmdopts['controllers_legend'].split(',') @@ -145,21 +148,23 @@ def _run_cc(self, cli_args): self.logger.info("Inter-batch controller comparison complete") - def _run_sc(self, cli_args): + def _run_sc(self, cli_args: argparse.Namespace) -> None: # Use nice scenario names on graph legends if configured if self.cmdopts['scenarios_legend'] is not None: legend = self.cmdopts['scenarios_legend'].split(',') else: legend = self.scenarios + controller = ControllerGeneratorParser()(cli_args) + self.logger.info("Inter-batch comparison of %s across %s...", - self.cmdopts['controller'], + controller, self.scenarios) assert cli_args.bc_univar, \ "inter-scenario controller comparison only valid for univariate batch criteria" - comparator = intersc.UnivarInterScenarioComparator(self.cmdopts['controller'], + comparator = intersc.UnivarInterScenarioComparator(controller, self.scenarios, self.batch_roots, self.stage5_roots, @@ -171,10 +176,12 @@ def _run_sc(self, cli_args): legend=legend) self.logger.info("Inter-batch comparison of %s across %s complete", - self.cmdopts['controller'], + controller, self.scenarios) - def _verify_comparability(self, controllers, cli_args): + def _verify_comparability(self, + controllers: tp.List[str], + cli_args: argparse.Namespace) -> None: """Check if the specified controllers can be compared. Comparable controllers have all been run on the same set of batch diff --git a/sierra/core/variables/batch_criteria.py b/sierra/core/variables/batch_criteria.py index 6f7648de..878917f1 100755 --- a/sierra/core/variables/batch_criteria.py +++ b/sierra/core/variables/batch_criteria.py @@ -60,7 +60,9 @@ def graph_xticks(self, exp_names: If not None, then this list of directories will be used to calculate the ticks, rather than the results of - :ref:`gen_exp_names()`. + :ref:`gen_exp_names()`. This argument will be non-None + when calling this function from within a bivariate batch + criteria. """ @@ -84,7 +86,9 @@ def graph_xticklabels(self, exp_names: If not None, then these directories will be used to calculate the labels, rather than the results of - :ref:`gen_exp_names()`. + :ref:`gen_exp_names()`. This argument will be non-None + when calling this function from within a bivariate batch + criteria. """ raise NotImplementedError @@ -589,7 +593,7 @@ def graph_xticks(self, batch_output_root, self) - ynames = exp_names if exp_names else self.criteria1.gen_exp_names(cmdopts) + ynames = exp_names if exp_names else self.criteria1.gen_exp_names() for c1 in ynames: for x in all_dirs: @@ -608,7 +612,7 @@ def graph_yticks(self, all_dirs = utils.exp_range_calc(cmdopts["exp_range"], batch_output_root, self) - xnames = exp_names if exp_names else self.criteria2.gen_exp_names(cmdopts) + xnames = exp_names if exp_names else self.criteria2.gen_exp_names() for c2 in xnames: for y in all_dirs: @@ -623,17 +627,59 @@ def graph_xticklabels(self, cmdopts: types.Cmdopts, batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]: + """Generate x-axis labels. + + This bivariate function is one of the reasons the ``exp_names`` argument + is needed as an optional: when calculating xticks using say criteria1, + if the criteria uses :ref:`populations()` in the process, the criteria's + OWN ``gen_exp_names()`` will be used, which will result in bad directory + name calculations. This can be overcome by passing the list of exp names + to use at THIS level. + """ + names = [] + all_dirs = utils.exp_range_calc(cmdopts['exp_range'], + batch_output_root, + self) + + for c1 in self.criteria1.gen_exp_names(): + for x in all_dirs: + leaf = x.name + if c1 in leaf.split('+')[0]: + names.append(leaf) + break + return self.criteria1.graph_xticklabels(cmdopts, batch_output_root, - exp_names) + names) def graph_yticklabels(self, cmdopts: types.Cmdopts, batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]: + """Generate y-axis labels. + + This bivariate function is one of the reasons the ``exp_names`` argument + is needed as an optional: when calculating yticks using criteria2, + if the criteria uses :ref:`populations()` in the process, the criteria's + OWN ``gen_exp_names()`` will be used, which will result in bad directory + name calculations. This can be overcome by passing the list of exp names + to use at THIS level. + """ + names = [] + all_dirs = utils.exp_range_calc(cmdopts['exp_range'], + batch_output_root, + self) + + for c2 in self.criteria2.gen_exp_names(): + for x in all_dirs: + leaf = x.name + if c2 in leaf.split('+')[0]: + names.append(leaf) + break + return self.criteria2.graph_xticklabels(cmdopts, batch_output_root, - exp_names) + names) def graph_xlabel(self, cmdopts: types.Cmdopts) -> str: return self.criteria1.graph_xlabel(cmdopts) diff --git a/sierra/core/variables/population_size.py b/sierra/core/variables/population_size.py index aba62218..e492adec 100644 --- a/sierra/core/variables/population_size.py +++ b/sierra/core/variables/population_size.py @@ -8,6 +8,7 @@ import typing as tp import re import math +import pathlib # 3rd party packages @@ -26,6 +27,7 @@ def __init__(self, *args, **kwargs) -> None: def graph_xticks(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[float]: if exp_names is None: @@ -42,6 +44,7 @@ def graph_xticks(self, def graph_xticklabels(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]: if exp_names is None: diff --git a/sierra/core/variables/variable_density.py b/sierra/core/variables/variable_density.py index 3bf5b332..47e084af 100755 --- a/sierra/core/variables/variable_density.py +++ b/sierra/core/variables/variable_density.py @@ -69,7 +69,7 @@ def __call__(self, arg: str) -> types.CLIArgSpec: # remove batch criteria variable name, leaving only the spec sections = sections[1:] - assert len(sections) == 3,\ + assert len(sections) == 3, \ ("Spec must have 3 sections separated by '.'; " f"have {len(sections)} from '{arg}'") diff --git a/sierra/main.py b/sierra/main.py index 2c8e2ba0..4114c18f 100755 --- a/sierra/main.py +++ b/sierra/main.py @@ -115,6 +115,7 @@ def __call__(self) -> None: self.logger.info("Controller=%s, Scenario=%s", controller, scenario) pathset = batchroot.from_cmdline(self.args) + pipeline = Pipeline(self.args, controller, pathset) else: pipeline = Pipeline(self.args, None) diff --git a/sierra/plugins/platform/argos/cmdline.py b/sierra/plugins/platform/argos/cmdline.py index 80085daf..42a663d5 100755 --- a/sierra/plugins/platform/argos/cmdline.py +++ b/sierra/plugins/platform/argos/cmdline.py @@ -267,17 +267,16 @@ def init_stage1(self) -> None: action="store_true", default=False) - self.stage1_robots.add_argument("--n-robots", + self.stage1_robots.add_argument("--n-agents", help=""" - - The # robots that should be used in the - simulation. Can be used to override - batch criteria, or to supplement - experiments that do not set it so that - manual modification of input file is - unneccesary. - - """ + self.stage_usage_doc([1]), + The # agents (robots) that should + be used in the simulation. Can be + used to override batch criteria, or + to supplement experiments that do + not set it so that manual + modification of input file is + unneccesary. + """ + self.stage_usage_doc([1]), type=int, default=None) @@ -287,7 +286,6 @@ def cmdopts_update(cli_args, cmdopts: types.Cmdopts) -> None: """ hpc.cmdline.HPCCmdline.cmdopts_update(cli_args, cmdopts) - updates = { # Stage 1 'n_agents': cli_args.n_agents, diff --git a/sierra/plugins/platform/argos/variables/population_constant_density.py b/sierra/plugins/platform/argos/variables/population_constant_density.py index 9928965a..6947c984 100755 --- a/sierra/plugins/platform/argos/variables/population_constant_density.py +++ b/sierra/plugins/platform/argos/variables/population_constant_density.py @@ -87,6 +87,7 @@ def gen_exp_names(self) -> tp.List[str]: def graph_xticks(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[float]: if exp_names is None: @@ -103,6 +104,7 @@ def graph_xticks(self, def graph_xticklabels(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]: if exp_names is None: exp_names = self.gen_exp_names() diff --git a/sierra/plugins/platform/argos/variables/population_variable_density.py b/sierra/plugins/platform/argos/variables/population_variable_density.py index 4e68fd30..e30a9862 100755 --- a/sierra/plugins/platform/argos/variables/population_variable_density.py +++ b/sierra/plugins/platform/argos/variables/population_variable_density.py @@ -77,6 +77,7 @@ def gen_exp_names(self) -> tp.List[str]: def graph_xticks(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[float]: if exp_names is None: @@ -86,9 +87,10 @@ def graph_xticks(self, def graph_xticklabels(self, cmdopts: types.Cmdopts, + batch_output_root: pathlib.Path, exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]: return list(map(lambda x: str(round(x, 4)), - self.graph_xticks(cmdopts, exp_names))) + self.graph_xticks(cmdopts, batch_output_root, exp_names))) def graph_xlabel(self, cmdopts: types.Cmdopts) -> str: return r"Population Density" diff --git a/sierra/plugins/platform/ros1gazebo/variables/population_size.py b/sierra/plugins/platform/ros1gazebo/variables/population_size.py index 0da37b89..80fd0ee3 100755 --- a/sierra/plugins/platform/ros1gazebo/variables/population_size.py +++ b/sierra/plugins/platform/ros1gazebo/variables/population_size.py @@ -97,7 +97,7 @@ def gen_tag_addlist(self) -> tp.List[xml.TagAddList]: exp_adds.append(xml.TagAdd("./master/group/[@ns='sierra']", "param", { - 'name': 'experiment/n_robots', + 'name': 'experiment/n_agents', 'value': str(s) }, False)) @@ -157,7 +157,7 @@ def gen_exp_names(self) -> tp.List[str]: adds = self.gen_tag_addlist() return ['exp' + str(x) for x in range(0, len(adds))] - def n_robots(self, exp_num: int) -> int: + def n_agents(self, exp_num: int) -> int: return int(len(self.tag_adds[exp_num]) / len(self.tag_adds[0]))