diff --git a/run.py b/run.py index efa7456..e25834c 100755 --- a/run.py +++ b/run.py @@ -1,30 +1,67 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +run.py: PREP-SHOT Entry Point +============================= + +██████ ██████ ███████ ██████ ███████ █ █ █████ ███████ +█ █ █ █ █ █ █ █ █ █ █ █ █ +█ █ █ █ █ █ █ █ █ █ █ █ █ +██████ ██████ ███████ ██████ ███████ ███████ ███████ █ █ █ +█ █ █ █ █ █ █ █ █ █ █ +█ █ █ █ █ █ █ █ █ █ █ +█ █ █ ███████ █ ███████ █ █ █████ █ + +This script serves as the main entry point for the PREP-SHOT. It initializes +the PREP-SHOT, loads the configuration data, parses command line arguments, +and starts the primary process. + +Usage: + To run this script from the command line, use the following command: + $ python run.py -- + or simply: + $ python run.py + $ ./run.py + +Author: + Zhanwei LIU + +Last Updated: + 2024-06-25 +""" + import logging from os import path, makedirs + from prepshot.load_data import load_json, get_required_config_data, load_data from prepshot.logs import setup_logging, log_parameter_info from prepshot.model import create_model from prepshot.parameters import parse_arguments -from prepshot.solver import build_solver, solve_model -from prepshot.utils import extract_result, update_output_filename -import pandas as pd +from prepshot.utils import ( + extract_result, update_output_filename, solve_model, save_to_excel +) # Name of the configuration file and parameters file in root directory. CONFIG_FILENAME = 'config.json' -PARAMS_FILENAME = 'params.json' - -def setup(params_data, args): - """ - Load data and set up logging. - Args: - params_data (dict): Dictionary of parameters data. - args (argparse.Namespace): Arguments parsed by argparse. - - Returns: - tuple: A tuple containing the parameters dictionary and the output filename. +def setup(setting, args): + """Load data and set up logging. + + Parameters + ---------- + setting : dict + Dictionary of parameters data. + args : argparse.Namespace + Arguments parsed by argparse. + + Returns + ------- + tuple + A tuple containing the parameters dictionary and + the output filename. """ - # Load configuration data - config_data = load_json(CONFIG_FILENAME) + config_data = setting + params_data = setting['data_parameters'] required_config_data = get_required_config_data(config_data) # Get the path to input folder. @@ -32,12 +69,14 @@ def setup(params_data, args): input_filename = str(config_data['general_parameters']['input_folder']) input_filepath = path.join(filepath, input_filename) - # update command-line arguments to set different scenarios easily. + # Overwrite the parameters in config.json based on command-line arguments + # which aims to run different scenarios easily. for param in params_data.keys(): if getattr(args, param) is None: pass else: - params_data[param]["file_name"] = params_data[param]["file_name"] + f"_{getattr(args, param)}" + params_data[param]["file_name"] = params_data[param]["file_name"] \ + + f"_{getattr(args, param)}" # Load parameters data parameters = load_data(params_data, input_filepath) @@ -45,74 +84,62 @@ def setup(params_data, args): # Combine the configuration data and parameters data. parameters.update(required_config_data) - # Set up logging setup_logging() log_parameter_info(config_data) - + # Get the output folder. - output_folder = './' + str(config_data['general_parameters']['output_folder']) + output_folder = './' \ + + str(config_data['general_parameters']['output_folder']) if not path.exists(output_folder): makedirs(output_folder) - logging.warning(f"Folder {output_folder} created") + logging.warning( + "Folder %s created", output_folder + ) # Get the output filename. - output_filename = output_folder + '/' + str(config_data['general_parameters']['output_filename']) + output_filename = output_folder + '/' \ + + str(config_data['general_parameters']['output_filename']) return parameters, output_filename - def run_model(parameters, output_filename, args): - """ - Create and solve the model. - - Args: - parameters (dict): Dictionary of parameters for the model. - output_filename (str): The name of the output file. - args (argparse.Namespace): Arguments parsed by argparse. - - Returns: - None + """Create and solve the model. + + Parameters + ---------- + parameters : dict + Dictionary of parameters for the model. + output_filename : str + The name of the output file. + args : argparse.Namespace + Arguments parsed by argparse. """ model = create_model(parameters) - exit() output_filename = update_output_filename(output_filename, args) - solver = build_solver(parameters) - solved = solve_model(model, solver, parameters) + solved = solve_model(model, parameters) + exit() if solved: ds = extract_result(model, isinflow=parameters['isinflow']) ds.to_netcdf(f'{output_filename}.nc') - logging.info("Results are written to %s.nc", output_filename) - # Write results to excel files. - with pd.ExcelWriter(f'{output_filename}.xlsx') as writer: - for key in ds.data_vars: - if len(ds[key].shape) == 0: - df = pd.DataFrame([ds[key].values.max()], columns=[key]) - else: - df = ds[key].to_dataframe() - df.to_excel(writer, sheet_name=key, merge_cells=False) + logging.info( + "Results are written to %s.nc", output_filename + ) + save_to_excel(ds, output_filename) logging.info("Results are written to separate excel files") - - def main(): + """The main function of the PREP-SHOT model. """ - The main function of the PREP-SHOT model. - - Args: - None - - Returns: - None - """ - # Load parameters data. - params_data = load_json(PARAMS_FILENAME) + # Load parameters by parsing config.json and command-line arguments. + # command-line arguments will overwrite the parameters in config.json. + setting = load_json(CONFIG_FILENAME) + params_data = setting['data_parameters'] params_list = [params_data[key]["file_name"] for key in params_data] args = parse_arguments(params_list) - # Set up model. - parameters, output_filename = setup(params_data, args) + # Load model general parameters and setup logging. + parameters, output_filename = setup(setting, args) - # Run model. run_model(parameters, output_filename, args) if __name__ == "__main__":