|
| 1 | +from pathlib import Path |
| 2 | + |
| 3 | +import metomi.isodatetime.dumpers |
| 4 | +import metomi.isodatetime.parsers |
| 5 | +from yaml import safe_load |
| 6 | + |
| 7 | +from legacy_date_conversions import * |
| 8 | + |
| 9 | +# set up logging |
| 10 | +import logging |
| 11 | +logging.basicConfig() |
| 12 | +logger = logging.getLogger(__name__) |
| 13 | +logger.setLevel(logging.INFO) |
| 14 | + |
| 15 | +# Global variables just set to reduce typing a little. |
| 16 | +duration_parser = metomi.isodatetime.parsers.DurationParser() |
| 17 | +one_year = duration_parser.parse("P1Y") |
| 18 | +time_dumper = metomi.isodatetime.dumpers.TimePointDumper() |
| 19 | +time_parser = metomi.isodatetime.parsers.TimePointParser(assumed_time_zone=(0, 0)) |
| 20 | + |
| 21 | +class Climatology(object): |
| 22 | + def __init__(self, component, frequency, interval_years): |
| 23 | + """Initialize the climatology object |
| 24 | +
|
| 25 | + Args: |
| 26 | + component: Data source for the climatology |
| 27 | + frequency: 'mon' or 'yr' |
| 28 | + interval_years: Number of years in the averaging window |
| 29 | + """ |
| 30 | + logger.debug(f"Initializing climatology for component '{component}'") |
| 31 | + |
| 32 | + self.component = component |
| 33 | + self.frequency = frequency |
| 34 | + self.interval_years = interval_years |
| 35 | + |
| 36 | + def graph(self): |
| 37 | + """Generate the cylc task graph string for the climatology. |
| 38 | + """ |
| 39 | + |
| 40 | + return graph |
| 41 | + |
| 42 | + def definition(self: |
| 43 | + """Generate the cylc task definitions for the climatology. |
| 44 | + """ |
| 45 | + |
| 46 | + return definitions |
| 47 | + |
| 48 | +def task_generator(yaml_): |
| 49 | + for component in yaml_["postprocess"]["components"]: |
| 50 | + if 'climatology' in component: |
| 51 | + for item in array: |
| 52 | + frequency = component["climatology"]["frequency"] |
| 53 | + interval_years = component["climatology"]["interval_years"] |
| 54 | + climatology_info = Climatology(component, frequency, interval_years) |
| 55 | + yield climatology_info |
| 56 | + |
| 57 | +def task_definitions(yaml_): |
| 58 | + """Return the task definitions for all requested climatologies. |
| 59 | +
|
| 60 | + Args: |
| 61 | + yaml_: Dictionary experiment yaml. |
| 62 | +
|
| 63 | + Returns: |
| 64 | + String containing the task defintions. |
| 65 | + """ |
| 66 | + logger.debug("About to generate all task definitions") |
| 67 | + definitions = "" |
| 68 | + for script_info in task_generator(yaml_): |
| 69 | + definitions += script_info.definition(chunk) |
| 70 | + logger.debug("Finished generating all task definitions") |
| 71 | + return definitions |
| 72 | + |
| 73 | +def task_graphs(yaml_): |
| 74 | + """Return the task graphs for all requested climatologies. |
| 75 | +
|
| 76 | + Args: |
| 77 | + yaml_: Dictionary experiment yaml. |
| 78 | +
|
| 79 | + Returns: |
| 80 | + String containing the task graphs. |
| 81 | + """ |
| 82 | + logger.debug("About to generate all task graphs") |
| 83 | + graph = "" |
| 84 | + for script_info in task_generator(yaml_): |
| 85 | + graph += script_info.graph(chunk) |
| 86 | + logger.debug("Finished generating all task graphs") |
| 87 | + return graph |
| 88 | + |
| 89 | +def get_climatology_info(experiment_yaml, info_type): |
| 90 | + """Return requested climatology information from the experiment yaml |
| 91 | +
|
| 92 | + Args: |
| 93 | + experiment_yaml: Path to the experiment yaml file. |
| 94 | + info_type: String that tells which kind of output to make (graph or definition). |
| 95 | + """ |
| 96 | + logger.debug("get_climatology_info: starting") |
| 97 | + |
| 98 | + with open(experiment_yaml) as file_: |
| 99 | + yaml_ = safe_load(file_) |
| 100 | + |
| 101 | + # Convert strings to date objects. |
| 102 | + experiment_start = time_parser.parse(experiment_start) |
| 103 | + experiment_stop = time_parser.parse(experiment_stop) |
| 104 | + chunk1 = duration_parser.parse(chunk1) |
| 105 | + if chunk2 is not None: |
| 106 | + chunk2 = duration_parser.parse(chunk2) |
| 107 | + |
| 108 | + # split the pp_components into a list |
| 109 | + experiment_components = experiment_components.split() |
| 110 | + |
| 111 | + if info_type == "task-graph": |
| 112 | + logger.debug("about to return graph") |
| 113 | + return task_graphs(yaml_) |
| 114 | + elif info_type == "task-definitions": |
| 115 | + logger.debug("about to return definitions") |
| 116 | + return task_definitions(yaml_) |
| 117 | + raise ValueError(f"Invalid information type: {info_type}.") |
0 commit comments