# -*- coding: utf-8 -*-
"""
General CLI utility functions.
"""
import os
import logging
from copy import deepcopy
from warnings import warn
import pandas as pd
from gaps.pipeline import Status
from rex.utilities.loggers import init_mult
from reV.utilities import ModuleName, SupplyCurveField
from reV.utilities.exceptions import ConfigWarning, PipelineError
logger = logging.getLogger(__name__)
[docs]
def init_cli_logging(name, log_directory, verbose):
"""Initialize CLI logger
Parameters
----------
name : str
The name to use for the log file written to disk.
log_directory : str
Path to log file output directory.
verbose : bool
Option to make logger verbose (DEBUG).
"""
init_mult(name, log_directory, modules=['reV', 'rex'], verbose=verbose)
logger.info("Initialized reV/rex {}loggers with name {!r} and log "
"directory {!r}"
.format("verbose " if verbose else "", name,
str(log_directory)))
[docs]
def parse_from_pipeline(config, out_dir, config_key, target_modules):
"""Parse the out file from target modules and set as the values for key.
This function only updates the ``config_key`` input if it is set to
``"PIPELINE"``.
Parameters
----------
config : dict
Configuration dictionary. The ``config_key`` will be updated in
this dictionary if it is set to ``"PIPELINE"``.
out_dir : str
Path to pipeline project directory where config and status files
are located. The status file is expected to be in this
directory.
config_key : str
Key in config files to replace with ``"out_file"`` value(s) from
previous pipeline step.
target_modules : list of str | list of `ModuleName`
List of (previous) target modules to parse for the
``config_key``.
Returns
-------
dict
Input config dictionary with updated ``config_key`` input.
Raises
------
PipelineError
If ``"out_file"`` not found in previous target module status
files.
"""
if config.get(config_key, None) == 'PIPELINE':
for target_module in target_modules:
gen_config_key = "gen" in config_key
module_sca = target_module == ModuleName.SUPPLY_CURVE_AGGREGATION
if gen_config_key and module_sca:
target_key = "gen_fpath"
else:
target_key = "out_file"
val = Status.parse_step_status(out_dir, target_module, target_key)
if len(val) == 1:
break
else:
raise PipelineError('Could not parse {} from previous '
'pipeline jobs.'.format(config_key))
config[config_key] = val[0]
logger.info('Config using the following pipeline input for {}: {}'
.format(config_key, val[0]))
return config
[docs]
def compile_descriptions(cols=None):
"""Compile a meta table with reV column descriptions.
Descriptions are pulled from the
:class:`~reV.utilities.SupplyCurveField` enum, which
contains the known reV supply curve field descriptions. Columns
which do not have a known description are excluded from the
output.
Parameters
----------
cols : iterable, optional
Optional iterable of column names to include in the output.
By default, ``None``, which compiles all known reV supply curve
field descriptions.
Returns
-------
pd.DataFrame
Pandas DataFrame containing column names, corresponding units,
and descriptions for each column. Only columns that have a known
description are included in the output.
"""
if not cols:
cols = [c.value for c in SupplyCurveField]
data = []
for col in cols:
try:
scf = SupplyCurveField(col)
except ValueError:
continue
if scf.description is None:
continue
data.append((str(scf), scf.units, scf.description))
return pd.DataFrame(data, columns=["reV Column", "Units", "Description"])
[docs]
def add_to_run_attrs(run_attrs=None, config_file=None,
module=ModuleName.GENERATION):
"""Add config and project directory to run attrs
Parameters
----------
run_attrs : dict, optional
Existing `run_attrs` (if any). By default, ``None``.
config_file : str, optional
Path to config file used for this module's run (if applicable).
This is used to store the run config in the output attrs.
By default, ``None``.
module : :obj:`~reV.utilities.ModuleName`, optional
Module that this run represents.
By default, ``ModuleName.GENERATION``.
Returns
-------
dict
Run attributes that can be written to the file's attrs.
"""
out = {}
if run_attrs:
out = deepcopy(run_attrs)
out[f"{module}_config_fp"] = str(config_file)
out[f"{module}_config"] = "{}"
if config_file and os.path.exists(config_file):
with open(config_file, "r") as fh:
out[f"{module}_config"] = fh.read()
return out