Source code for watts.plugin_gcmat
# SPDX-FileCopyrightText: 2024 UChicago Argonne, LLC
# SPDX-License-Identifier: MIT
from pathlib import Path
import shutil
import subprocess
from typing import List, Optional
import os
import pandas as pd
from .plugin import Plugin
from .results import Results, ExecInfo
from .fileutils import PathLike
from .parameters import Parameters
from .template import TemplateRenderer
[docs]
class ResultsGCMAT(Results):
"""GCMAT simulation results
Parameters
----------
params
Parameters used to generate inputs
exec_info
Execution information (job ID, plugin name, time, etc.)
inputs
List of input files
outputs
List of output files
Attributes
----------
stdout
Standard output from GCMAT run
csv_data
Data from the output CSV file
"""
def __init__(self, params: Parameters, exec_info: ExecInfo,
inputs: List[PathLike], outputs: List[PathLike]):
super().__init__(params, exec_info, inputs, outputs)
self.csv_data = self._get_gcmat_csv_data()
def _get_gcmat_csv_data(self) -> pd.DataFrame:
"""Read GCMAT output CSV file and return results as a DataFrame"""
output_file = next((p for p in self.outputs if p.name == 'GUIOutputs.csv'), None)
if output_file and output_file.exists():
return pd.read_csv(output_file)
else:
return pd.DataFrame() # Return an empty DataFrame if no CSV file is found
[docs]
class PluginGCMAT(Plugin):
"""Plugin for running GCMAT
Parameters
----------
template_file
Template file used to generate the input files
extra_inputs
Extra (non-templated) input files
show_stdout
Whether to display output from stdout when GCMAT is run
show_stderr
Whether to display output from stderr when GCMAT is run
"""
def __init__(self, template_file: PathLike,
extra_inputs: Optional[List[PathLike]] = None,
show_stdout: bool = False, show_stderr: bool = False):
super().__init__(extra_inputs, show_stdout, show_stderr)
self.template_file = template_file
self.plugin_name = 'GCMAT'
self.renderer = TemplateRenderer(template_file)
self.gcmat_dir = os.getenv('GCMAT_DIR')
if not self.gcmat_dir:
raise EnvironmentError("GCMAT_DIR environment variable is not set.")
# Include './run_repast.sh' as the executable and all files in the 'data' folder as default extra inputs
self.executable = Path(self.gcmat_dir) / "run_repast.sh"
self.default_extra_inputs = list((Path(self.gcmat_dir) / "complete_model" / "data").glob("**/*"))
# Initialize output_folder attribute
self.output_folder = None
[docs]
def prerun(self, params: Parameters) -> None:
"""Generate GCMAT input files
Parameters
----------
params
Parameters used by the GCMAT template
"""
# Render the template to create the input file
input_file = Path("gc_input.txt")
self.renderer(params, filename=input_file)
# Copy the input file to the required directory
model_directory = Path(self.gcmat_dir) / "complete_model"
target_directory = model_directory / "data/scenariosNuclear/default_UserInputs"
target_directory.mkdir(parents=True, exist_ok=True)
shutil.copy(input_file, target_directory / "demandScenarioV2.txt")
[docs]
def run(self, end_year: int = 2080, output_folder: str = "testout", **kwargs):
"""Run GCMAT
Parameters
----------
end_year
The year to end the simulation
output_folder
The folder where outputs will be stored
kwargs
Additional keyword arguments to pass to the subprocess
"""
# use the absolute path for the output folder
self.output_folder = os.path.join(self.gcmat_dir, output_folder)
param_string = f'1\tendAt\t{end_year}'
command = [str(self.executable), param_string, subprocess.check_output('realpath .', shell=True).strip().decode('utf-8'), output_folder]
# Run the GCMAT simulation
subprocess.run(command, cwd=self.gcmat_dir, **kwargs)
[docs]
def postrun(self, params: Parameters, exec_info: ExecInfo) -> ResultsGCMAT:
"""Collect information from GCMAT simulation and create results object
Parameters
----------
params
Parameters used to create GCMAT model
exec_info
Execution information
Returns
-------
GCMAT results object
"""
output_folder = Path(self.output_folder) # Retrieve the stored
# Only collect the GUIOutputs.csv file
# can add more files if needed
outputs = []
gui_outputs_file = output_folder / "GUIOutputs.csv"
if gui_outputs_file.exists():
outputs.append(gui_outputs_file)
return ResultsGCMAT(params, exec_info, self.extra_inputs, outputs)