|
| 1 | +# |
| 2 | +#@HEADER |
| 3 | +############################################################################### |
| 4 | +# |
| 5 | +# lbsJSONTaskLister.py |
| 6 | +# DARMA/LB-analysis-framework => LB Analysis Framework |
| 7 | +# |
| 8 | +# Copyright 2019-2024 National Technology & Engineering Solutions of Sandia, LLC |
| 9 | +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. |
| 10 | +# Government retains certain rights in this software. |
| 11 | +# |
| 12 | +# Redistribution and use in source and binary forms, with or without |
| 13 | +# modification, are permitted provided that the following conditions are met: |
| 14 | +# |
| 15 | +# * Redistributions of source code must retain the above copyright notice, |
| 16 | +# this list of conditions and the following disclaimer. |
| 17 | +# |
| 18 | +# * Redistributions in binary form must reproduce the above copyright notice, |
| 19 | +# this list of conditions and the following disclaimer in the documentation |
| 20 | +# and/or other materials provided with the distribution. |
| 21 | +# |
| 22 | +# * Neither the name of the copyright holder nor the names of its |
| 23 | +# contributors may be used to endorse or promote products derived from this |
| 24 | +# software without specific prior written permission. |
| 25 | +# |
| 26 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 27 | +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 28 | +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 29 | +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 30 | +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 31 | +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 32 | +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 33 | +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 34 | +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 35 | +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 36 | +# POSSIBILITY OF SUCH DAMAGE. |
| 37 | +# |
| 38 | +# Questions? Contact [email protected] |
| 39 | +# |
| 40 | +############################################################################### |
| 41 | +#@HEADER |
| 42 | +# |
| 43 | +""" |
| 44 | +Utility to generate a yaml containing lists of tasks associated to their respective ranks, |
| 45 | +from the last phase and last sub-iteration of input JSON files. |
| 46 | +
|
| 47 | +""" |
| 48 | + |
| 49 | +import os |
| 50 | +import sys |
| 51 | +import json |
| 52 | +import yaml |
| 53 | +import argparse |
| 54 | +import re |
| 55 | + |
| 56 | +from lbaf.IO.lbsVTDataReader import LoadReader |
| 57 | +from lbaf.Utils.lbsLogging import get_logger, Logger |
| 58 | + |
| 59 | +def process_files(directory, file_stem, file_suffix, logger: Logger): |
| 60 | + reader = LoadReader( |
| 61 | + file_prefix = directory + file_stem, |
| 62 | + logger = logger, |
| 63 | + file_suffix = file_suffix |
| 64 | + ) |
| 65 | + |
| 66 | + tasks = {} |
| 67 | + n_ranks = reader.n_ranks |
| 68 | + |
| 69 | + try: |
| 70 | + for rank in range(n_ranks): |
| 71 | + _, data = reader._load_vt_file(rank) |
| 72 | + phases = data.get("phases", []) |
| 73 | + if not phases: |
| 74 | + logger.warning("No phases found for rank %s", str(rank)) |
| 75 | + continue |
| 76 | + |
| 77 | + last_phase = phases[-1] |
| 78 | + |
| 79 | + if "lb_iterations" in last_phase: |
| 80 | + lb_iterations = last_phase["lb_iterations"] |
| 81 | + if lb_iterations: |
| 82 | + last_lb_iteration = lb_iterations[-1] |
| 83 | + iteration_tasks = [task["entity"].get("seq_id", task["entity"].get("id")) for task in last_lb_iteration.get("tasks", [])] |
| 84 | + tasks[rank] = iteration_tasks |
| 85 | + else: |
| 86 | + logger.warning("No lb_iterations found in the last phase of rank %s", str(rank)) |
| 87 | + else: |
| 88 | + phase_tasks = [task["entity"].get("seq_id", task["entity"].get("id")) for task in last_phase.get("tasks", [])] |
| 89 | + tasks[rank] = phase_tasks |
| 90 | + except (json.JSONDecodeError, KeyError, ValueError, IndexError) as e: |
| 91 | + logger.error("Error processing rank %s: %s", str(rank), e) |
| 92 | + sys.exit(1) |
| 93 | + |
| 94 | + return tasks |
| 95 | + |
| 96 | +def main(): |
| 97 | + parser = argparse.ArgumentParser(description="Extract tasks from JSON files.") |
| 98 | + parser.add_argument("directory", type=str, help="Directory containing JSON files.") |
| 99 | + parser.add_argument("--file-stem", type=str, default="data", help="File stem for JSON files (default: 'data').") |
| 100 | + parser.add_argument("--file-suffix", type=str, default="json", help="File suffix for JSON files (default: 'json').") |
| 101 | + parser.add_argument("--output", type=str, default="tasks.yml", help="Output YAML file (default: 'tasks.yml').") |
| 102 | + |
| 103 | + args = parser.parse_args() |
| 104 | + |
| 105 | + directory = args.directory |
| 106 | + file_stem = args.file_stem |
| 107 | + file_suffix = args.file_suffix |
| 108 | + output_file = args.output |
| 109 | + |
| 110 | + logger = get_logger() |
| 111 | + |
| 112 | + if not os.path.isdir(directory): |
| 113 | + logger.error("Directory not found: %s", directory) |
| 114 | + return |
| 115 | + |
| 116 | + tasks = process_files(directory, file_stem, file_suffix, logger) |
| 117 | + |
| 118 | + try: |
| 119 | + with open(output_file, 'w') as file: |
| 120 | + yaml.safe_dump(tasks, file) |
| 121 | + logger.info("Tasks successfully written to %s", output_file) |
| 122 | + except IOError as e: |
| 123 | + logger.error("Error writing to %s: %s", output_file, e) |
| 124 | + |
| 125 | +if __name__ == "__main__": |
| 126 | + main() |
0 commit comments