From b1f671e0bae33ff2a86e0dd10337369cdbfcbed3 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 22:44:15 -0500 Subject: [PATCH 01/11] changing logging output, making the tool function more like a command line tool --- src/acom_music_box/main.py | 118 ++++++++++++++------------------ src/acom_music_box/music_box.py | 22 ++++-- 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index d3f1c01c..47223e41 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -1,96 +1,84 @@ import os import argparse from acom_music_box import MusicBox - - -import math import datetime import sys - import logging -logger = logging.getLogger(__name__) - - -# configure argparse for key-value pairs -class KeyValueAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - for value in values: - key, val = value.split('=') - setattr(namespace, key, val) -# Retrieve named arguments from the command line and -# return in a dictionary of keywords. -# argPairs = list of arguments, probably from sys.argv[1:] -# named arguments are formatted like this=3.14159 -# return dictionary of keywords and values - - -def getArgsDictionary(argPairs): +def parse_arguments(): parser = argparse.ArgumentParser( - description='Process some key=value pairs.') + description='MusicBox simulation runner.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument( + '-c', '--config', + type=str, + required=True, + help='Path to the configuration file.' + ) + parser.add_argument( + '-o', '--output', + type=str, + help='Path to save the output file, including the file name. If not provided, result will be printed to the console.' + ) parser.add_argument( - 'key_value_pairs', - nargs='+', # This means one or more arguments are expected - action=KeyValueAction, - help="Arguments in key=value format. Example: configFile=my_config.json" + '-v', '--verbose', + action='store_true', + help='Enable debug logging.' ) + return parser.parse_args() - argDict = vars(parser.parse_args(argPairs)) # return dictionary - return (argDict) +def setup_logging(verbose): + log_level = logging.DEBUG if verbose else logging.INFO + logging.basicConfig( + level=log_level, + format='%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + ) def main(): - logging.basicConfig(stream=sys.stdout, level=logging.INFO) - logger.info("{}".format(__file__)) - logger.info("Start time: {}".format(datetime.datetime.now())) + start = datetime.datetime.now() + + args = parse_arguments() + setup_logging(args.verbose) - logger.info("Hello, MusicBox World!") - logger.info("Working directory = {}".format(os.getcwd())) + logger = logging.getLogger(__name__) + + logger.debug(f"{__file__}") + logger.info(f"Start time: {start}") + + logger.debug(f"Working directory = {os.getcwd()}") # retrieve and parse the command-line arguments - myArgs = getArgsDictionary(sys.argv[1:]) - logger.info("Command line = {}".format(myArgs)) + logger.debug(f"Command line arguments: {vars(args)}") # set up the home configuration file - musicBoxConfigFile = None - if ("configFile" in myArgs): - musicBoxConfigFile = myArgs.get("configFile") - - # set up the output directory - musicBoxOutputDir = ".\\" # default - if ("outputDir" in myArgs): - musicBoxOutputDir = myArgs.get("outputDir") - - # check for required arguments and provide examples - if (musicBoxConfigFile is None): - errorString = "Error: The configFile parameter is required." - errorString += ( - " Example: configFile={}" .format( - os.path.join( - "tests", - "configs", - "analytical_config", - "my_config.json"))) - raise Exception(errorString) + musicBoxConfigFile = args.config + + # set up the output path (if provided) + musicBoxOutputPath = args.output # create and load a MusicBox object myBox = MusicBox() - logging.info("configuration file = {}".format(musicBoxConfigFile)) + logger.debug(f"Configuration file = {musicBoxConfigFile}") myBox.readConditionsFromJson(musicBoxConfigFile) - logger.info("myBox = {}".format(myBox)) - # create solver and solve, writing output to requested directory - campConfig = os.path.join( + # create solver and solve + config_path = os.path.join( os.path.dirname(musicBoxConfigFile), myBox.config_file) - logger.info("CAMP config = {}".format(campConfig)) - myBox.create_solver(campConfig) - logger.info("myBox.solver = {}".format(myBox.solver)) - mySolution = myBox.solve(os.path.join(musicBoxOutputDir, "mySolution.csv")) - # logger.info("mySolution = {}".format(mySolution)) + myBox.create_solver(config_path) + result = myBox.solve(musicBoxOutputPath) + + if musicBoxOutputPath is None: + logger.info(result) + + end = datetime.datetime.now() + logger.info(f"End time: {end}") + logger.info(f"Elapsed time: {end - start} seconds") - logger.info("End time: {}".format(datetime.datetime.now())) sys.exit(0) diff --git a/src/acom_music_box/music_box.py b/src/acom_music_box/music_box.py index 3eb0f922..5cae95d0 100644 --- a/src/acom_music_box/music_box.py +++ b/src/acom_music_box/music_box.py @@ -10,7 +10,6 @@ import os import logging -logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) @@ -553,11 +552,22 @@ def solve(self, output_path=None): curr_time += self.box_model_options.chem_step_time # outputs to file if output is present - if (output_path is not None): - logger.info("path_to_output = {}".format(output_path)) - os.makedirs(os.path.dirname(output_path), exist_ok=True) - with open(output_path, 'w', newline='') as output: - writer = csv.writer(output) + if output_path is not None: + # Check if the output_path is a full path or just a file name + if os.path.dirname(output_path) == '': + # If output_path is just a filename, use the current directory + output_path = os.path.join(os.getcwd(), output_path) + elif not os.path.basename(output_path): + raise ValueError(f"Invalid output path: '{output_path}' does not contain a filename.") + + # Ensure the directory exists + dir_path = os.path.dirname(output_path) + if dir_path and not os.path.exists(dir_path): + os.makedirs(dir_path, exist_ok=True) + + # Write to the specified file path + with open(output_path, 'w', newline='') as output_file: + writer = csv.writer(output_file) writer.writerows(output_array) # returns output_array From 9997ab888293d81433c60feed0613483949f557a Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 22:49:35 -0500 Subject: [PATCH 02/11] adding color to log output --- pyproject.toml | 3 ++- src/acom_music_box/main.py | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bb75bd54..fd1b3964 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,8 @@ classifiers = ["License :: OSI Approved :: Apache Software License"] dynamic = ["version", "description"] dependencies = [ - "musica==0.7.3" + "musica==0.7.3", + "colorlog" ] [project.urls] diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index 47223e41..ae7e5f59 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -4,6 +4,7 @@ import datetime import sys import logging +import colorlog def parse_arguments(): parser = argparse.ArgumentParser( @@ -31,12 +32,28 @@ def parse_arguments(): def setup_logging(verbose): log_level = logging.DEBUG if verbose else logging.INFO - logging.basicConfig( - level=log_level, - format='%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S' + + # Create a colorlog formatter + formatter = colorlog.ColoredFormatter( + '%(log_color)s%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + log_colors={ + 'DEBUG': 'cyan', + 'INFO': 'green', + 'WARNING': 'yellow', + 'ERROR': 'red', + 'CRITICAL': 'bold_red', + } ) + # Create a console handler + console_handler = logging.StreamHandler() + console_handler.setLevel(log_level) + console_handler.setFormatter(formatter) + + # Configure the root logger + logging.basicConfig(level=log_level, handlers=[console_handler]) + def main(): start = datetime.datetime.now() From 505093d1ac18477dd0e7ca6a9a59979f304a861a Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 23:01:57 -0500 Subject: [PATCH 03/11] removing logs unless set with -v or -vv --- src/acom_music_box/main.py | 67 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index ae7e5f59..f1e848c2 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -24,42 +24,43 @@ def parse_arguments(): ) parser.add_argument( '-v', '--verbose', + action='count', + default=0, + help='Increase logging verbosity. Use -v for info, -vv for debug.' + ) + parser.add_argument( + '--color-output', action='store_true', - help='Enable debug logging.' + help='Enable color output for logs.' ) return parser.parse_args() - -def setup_logging(verbose): - log_level = logging.DEBUG if verbose else logging.INFO - - # Create a colorlog formatter - formatter = colorlog.ColoredFormatter( - '%(log_color)s%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - log_colors={ - 'DEBUG': 'cyan', - 'INFO': 'green', - 'WARNING': 'yellow', - 'ERROR': 'red', - 'CRITICAL': 'bold_red', - } - ) - - # Create a console handler - console_handler = logging.StreamHandler() - console_handler.setLevel(log_level) - console_handler.setFormatter(formatter) - - # Configure the root logger - logging.basicConfig(level=log_level, handlers=[console_handler]) - +def setup_logging(verbosity, color_output): + if verbosity >= 2: + log_level = logging.DEBUG + elif verbosity == 1: + log_level = logging.INFO + else: + log_level = logging.CRITICAL + + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') + if color_output: + color_formatter = colorlog.ColoredFormatter('%(log_color)s%(asctime)s - %(levelname)s - %(module)s.%(funcName)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S', log_colors={'DEBUG': 'green', 'INFO': 'cyan', 'WARNING': 'yellow', 'ERROR': 'red', 'CRITICAL': 'bold_red'}) + console_handler = logging.StreamHandler() + console_handler.setLevel(log_level) + console_handler.setFormatter(color_formatter) + logging.basicConfig(level=log_level, handlers=[console_handler]) + else: + console_handler = logging.StreamHandler() + console_handler.setLevel(log_level) + console_handler.setFormatter(formatter) + logging.basicConfig(level=log_level, handlers=[console_handler]) def main(): start = datetime.datetime.now() args = parse_arguments() - setup_logging(args.verbose) + setup_logging(args.verbose, args.color_output) logger = logging.getLogger(__name__) @@ -68,21 +69,16 @@ def main(): logger.debug(f"Working directory = {os.getcwd()}") - # retrieve and parse the command-line arguments - logger.debug(f"Command line arguments: {vars(args)}") - - # set up the home configuration file musicBoxConfigFile = args.config - # set up the output path (if provided) musicBoxOutputPath = args.output - # create and load a MusicBox object + # Create and load a MusicBox object myBox = MusicBox() logger.debug(f"Configuration file = {musicBoxConfigFile}") myBox.readConditionsFromJson(musicBoxConfigFile) - # create solver and solve + # Create solver and solve config_path = os.path.join( os.path.dirname(musicBoxConfigFile), myBox.config_file) @@ -90,7 +86,7 @@ def main(): result = myBox.solve(musicBoxOutputPath) if musicBoxOutputPath is None: - logger.info(result) + print(result) end = datetime.datetime.now() logger.info(f"End time: {end}") @@ -98,6 +94,5 @@ def main(): sys.exit(0) - if __name__ == "__main__": main() From 8b2bcc4f22a56aa98cfef8a422bc3da42bc78fd3 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 23:26:33 -0500 Subject: [PATCH 04/11] creating examples for use in solving --- .../use_case_7/camp_data/config.json | 6 - .../use_case_7/camp_data/mechanism.json | 135 ------------------ .../use_case_7/camp_data/species.json | 54 ------- .../bright_chamber/use_case_7/emissions.csv | 5 - .../bright_chamber/use_case_7/initial.csv | 2 - .../use_case_7/parking_lot_photo_rates.nc | Bin 280640 -> 0 bytes .../use_case_7/use_case_7_config.json | 83 ----------- .../use_case_7/wall_loss_rates_011519.txt | 6 - .../use_case_8/camp_data/config.json | 6 - .../use_case_8/camp_data/mechanism.json | 66 --------- .../use_case_8/camp_data/species.json | 54 ------- .../bright_chamber/use_case_8/emissions.csv | 5 - .../bright_chamber/use_case_8/emit_all.csv | 4 - .../bright_chamber/use_case_8/initial.csv | 2 - .../use_case_8/parking_lot_photo_rates.nc | Bin 280640 -> 0 bytes .../use_case_8/use_case_8_config.json | 95 ------------ .../use_case_8/wall_loss_rates_011519.txt | 6 - .../use_case_1/camp_data/config.json | 5 - .../use_case_1/camp_data/species.json | 54 ------- .../use_case_1/use_case_1_config.json | 32 ----- .../use_case_2/camp_data/config.json | 5 - .../use_case_2/camp_data/species.json | 54 ------- .../dark_chamber/use_case_2/initial.csv | 2 - .../use_case_2/use_case_2_config.json | 27 ---- .../use_case_3/camp_data/config.json | 5 - .../use_case_3/camp_data/species.json | 54 ------- .../dark_chamber/use_case_3/initial.csv | 2 - .../use_case_3/use_case_3_config.json | 25 ---- src/acom_music_box/__init__.py | 1 + src/acom_music_box/examples/__init__.py | 1 + .../configs/analytical}/camp_data/config.json | 0 .../analytical}/camp_data/reactions.json | 0 .../analytical}/camp_data/species.json | 0 .../analytical}/evolving_conditions.csv | 0 .../configs/analytical}/my_config.json | 0 .../carbon_bond_5}/camp_data/config.json | 0 .../carbon_bond_5}/camp_data/reactions.json | 0 .../carbon_bond_5}/camp_data/species.json | 0 .../carbon_bond_5}/initial_conditions.csv | 0 .../configs/carbon_bond_5}/my_config.json | 0 .../configs/chapman}/camp_data/config.json | 0 .../configs/chapman}/camp_data/reactions.json | 0 .../configs/chapman}/camp_data/species.json | 0 .../configs/chapman}/evolving_conditions.csv | 0 .../examples/configs/chapman}/my_config.json | 0 .../configs/flow_tube}/camp_data/config.json | 0 .../flow_tube}/camp_data/reactions.json | 0 .../configs/flow_tube}/camp_data/species.json | 0 .../flow_tube}/evolving_conditions.csv | 0 .../configs/flow_tube}/initial_conditions.csv | 0 .../configs/flow_tube}/my_config.json | 0 src/acom_music_box/examples/examples.py | 36 +++++ tests/test_analytical.py | 13 +- ...ase_mechanism.py => test_carbon_bond_5.py} | 16 ++- tests/test_chapman.py | 12 +- .../{test_wall_loss.py => test_flow_tube.py} | 12 +- 56 files changed, 72 insertions(+), 813 deletions(-) delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/camp_data/config.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/camp_data/mechanism.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/camp_data/species.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/emissions.csv delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/initial.csv delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/parking_lot_photo_rates.nc delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/use_case_7_config.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_7/wall_loss_rates_011519.txt delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/camp_data/config.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/camp_data/mechanism.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/camp_data/species.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/emissions.csv delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/emit_all.csv delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/initial.csv delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/parking_lot_photo_rates.nc delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/use_case_8_config.json delete mode 100644 examples/camp_examples/bright_chamber/use_case_8/wall_loss_rates_011519.txt delete mode 100644 examples/camp_examples/dark_chamber/use_case_1/camp_data/config.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_1/camp_data/species.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_1/use_case_1_config.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_2/camp_data/config.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_2/camp_data/species.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_2/initial.csv delete mode 100644 examples/camp_examples/dark_chamber/use_case_2/use_case_2_config.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_3/camp_data/config.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_3/camp_data/species.json delete mode 100644 examples/camp_examples/dark_chamber/use_case_3/initial.csv delete mode 100644 examples/camp_examples/dark_chamber/use_case_3/use_case_3_config.json create mode 100644 src/acom_music_box/examples/__init__.py rename {tests/configs/analytical_config => src/acom_music_box/examples/configs/analytical}/camp_data/config.json (100%) rename {tests/configs/analytical_config => src/acom_music_box/examples/configs/analytical}/camp_data/reactions.json (100%) rename {tests/configs/analytical_config => src/acom_music_box/examples/configs/analytical}/camp_data/species.json (100%) rename {tests/configs/analytical_config => src/acom_music_box/examples/configs/analytical}/evolving_conditions.csv (100%) rename {tests/configs/analytical_config => src/acom_music_box/examples/configs/analytical}/my_config.json (100%) rename {tests/configs/chapman_config => src/acom_music_box/examples/configs/carbon_bond_5}/camp_data/config.json (100%) rename {tests/configs/full_gas_phase_mechanism_config => src/acom_music_box/examples/configs/carbon_bond_5}/camp_data/reactions.json (100%) rename {tests/configs/full_gas_phase_mechanism_config => src/acom_music_box/examples/configs/carbon_bond_5}/camp_data/species.json (100%) rename {tests/configs/full_gas_phase_mechanism_config => src/acom_music_box/examples/configs/carbon_bond_5}/initial_conditions.csv (100%) rename {tests/configs/full_gas_phase_mechanism_config => src/acom_music_box/examples/configs/carbon_bond_5}/my_config.json (100%) rename {tests/configs/full_gas_phase_mechanism_config => src/acom_music_box/examples/configs/chapman}/camp_data/config.json (100%) rename {tests/configs/chapman_config => src/acom_music_box/examples/configs/chapman}/camp_data/reactions.json (100%) rename {tests/configs/chapman_config => src/acom_music_box/examples/configs/chapman}/camp_data/species.json (100%) rename {tests/configs/chapman_config => src/acom_music_box/examples/configs/chapman}/evolving_conditions.csv (100%) rename {tests/configs/chapman_config => src/acom_music_box/examples/configs/chapman}/my_config.json (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/camp_data/config.json (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/camp_data/reactions.json (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/camp_data/species.json (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/evolving_conditions.csv (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/initial_conditions.csv (100%) rename {tests/configs/wall_loss_config => src/acom_music_box/examples/configs/flow_tube}/my_config.json (100%) create mode 100644 src/acom_music_box/examples/examples.py rename tests/{test_full_gas_phase_mechanism.py => test_carbon_bond_5.py} (91%) rename tests/{test_wall_loss.py => test_flow_tube.py} (88%) diff --git a/examples/camp_examples/bright_chamber/use_case_7/camp_data/config.json b/examples/camp_examples/bright_chamber/use_case_7/camp_data/config.json deleted file mode 100644 index 4629149f..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/camp_data/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "camp-files" : [ - "camp_data/species.json", - "camp_data/mechanism.json" - ] -} diff --git a/examples/camp_examples/bright_chamber/use_case_7/camp_data/mechanism.json b/examples/camp_examples/bright_chamber/use_case_7/camp_data/mechanism.json deleted file mode 100644 index bc6b69de..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/camp_data/mechanism.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "camp-data" : [ - { - "name" : "Chapman", - "type" : "MECHANISM", - "reactions" : [ - { - "type" : "PHOTOLYSIS", - "reactants" : { - "O2" : { } - }, - "products" : { - "O" : { "yield" : 2.0 } - }, - "MUSICA name" : "O2_1" - }, - { - "type" : "PHOTOLYSIS", - "reactants" : { - "O3" : { } - }, - "products" : { - "O1D" : { }, - "O2" : { } - }, - "MUSICA name" : "O3_1" - }, - { - "type" : "PHOTOLYSIS", - "reactants" : { - "O3" : { } - }, - "products" : { - "O" : { }, - "O2" : { } - }, - "MUSICA name" : "O3_2" - }, - { - "type" : "ARRHENIUS", - "reactants" : { - "O1D" : { }, - "N2" : { } - }, - "products" : { - "O" : { }, - "N2" : { } - }, - "A" : 2.15e-11, - "C" : 110.0 - }, - { - "type" : "ARRHENIUS", - "reactants" : { - "O1D" : { }, - "O2" : { } - }, - "products" : { - "O" : { }, - "O2" : { } - }, - "A" : 3.3e-11, - "C" : 55.0 - }, - { - "type" : "ARRHENIUS", - "reactants" : { - "O" : { }, - "O3" : { } - }, - "products" : { - "O2" : { "yield" : 2.0 } - }, - "A" : 8.0e-12, - "C" : -2060.00 - }, - { - "type" : "ARRHENIUS", - "reactants" : { - "O" : { }, - "O2" : { }, - "M" : { } - }, - "products" : { - "O3" : { }, - "M" : { } - }, - "A" : 6.0e-34, - "B" : 2.4 - }, - { - "type" : "EMISSION", - "species" : "O1D", - "MUSICA name" : "O1D" - }, - { - "type" : "EMISSION", - "species" : "O", - "MUSICA name" : "O" - }, - { - "type" : "EMISSION", - "species" : "O3", - "MUSICA name" : "O3" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "N2", - "MUSICA name" : "N2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "O2", - "MUSICA name" : "O2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "CO2", - "MUSICA name" : "CO2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "Ar", - "MUSICA name" : "Ar" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "H2O", - "MUSICA name" : "H2O" - } - ] - } - ] -} - diff --git a/examples/camp_examples/bright_chamber/use_case_7/camp_data/species.json b/examples/camp_examples/bright_chamber/use_case_7/camp_data/species.json deleted file mode 100644 index 948aca00..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/camp_data/species.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "camp-data" : [ - { - "type" : "RELATIVE_TOLERANCE", - "value" : 1.0e-4 - }, - { - "name" : "M", - "type" : "CHEM_SPEC", - "tracer type" : "CONSTANT" - }, - { - "name" : "Ar", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "CO2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "H2O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "N2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O1D", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O3", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - } - ] -} - diff --git a/examples/camp_examples/bright_chamber/use_case_7/emissions.csv b/examples/camp_examples/bright_chamber/use_case_7/emissions.csv deleted file mode 100644 index 2553005b..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/emissions.csv +++ /dev/null @@ -1,5 +0,0 @@ -time.hr, EMIS.O1D, EMIS.O, EMIS.O3 -0.0, 0.0, 0.0, 0.0 -0.2, 0.1, 0.05, 0.05 -1.0, 0.2, 0.1, 0.1 -1.5, 0.0, 0.0, 0.0 diff --git a/examples/camp_examples/bright_chamber/use_case_7/initial.csv b/examples/camp_examples/bright_chamber/use_case_7/initial.csv deleted file mode 100644 index 2af07f8d..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/initial.csv +++ /dev/null @@ -1,2 +0,0 @@ -CONC.N2& CONC.O2& CONC.Ar& CONC.CO2& ENV.temperature& ENV.pressure.atm -3.29e1& 8.84& 3.92e-1& 1.69e-2& 298.0& 1.0 diff --git a/examples/camp_examples/bright_chamber/use_case_7/parking_lot_photo_rates.nc b/examples/camp_examples/bright_chamber/use_case_7/parking_lot_photo_rates.nc deleted file mode 100644 index fd3ba0f24bff980ce285055bed05231a4a0a570d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 280640 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 diff --git a/examples/camp_examples/bright_chamber/use_case_7/use_case_7_config.json b/examples/camp_examples/bright_chamber/use_case_7/use_case_7_config.json deleted file mode 100644 index 6cd6ef43..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/use_case_7_config.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "box model options" : { - "grid" : "box", - "chemistry time step [min]" : 5.0, - "output time step [hr]" : 1.0, - "simulation length [hr]" : 2.5, - "simulation start" : { - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - }, - "initial conditions" : { - "initial.csv" : { - "delimiter" : "&" - } - }, - "evolving conditions" : { - "emissions.csv" : { - "properties" : { - "time.hr" : { - "shift first entry to" :{ - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - } - } - }, - "wall_loss_rates_011519.txt" : { - "delimiter" : ";", - "time axis" : "columns", - "properties" : { - "simtime" : { - "MusicBox name" : "time", - "units" : "hr", - "shift first entry to" :{ - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - }, - "*" : { - "MusicBox name" : "LOSS.*", - "units" : "min-1" - } - } - }, - "parking_lot_photo_rates.nc" : { - "time offset" : { "years" : 15 }, - "properties" : { - "*" : { "MusicBox name" : "PHOT.*" }, - "time" : { - "MusicBox name" : "time", - "shift first entry to" : { - "year" : 2020, - "month" : 1, - "day" : 1, - "time zone" : "UTC-8" - } - } - } - } - }, - "model components" : [ - { - "type" : "CAMP", - "configuration file" : "camp_data/config.json", - "override species" : { - "M" : { "mixing ratio mol mol-1" : 1.0 } - }, - "suppress output" : { - "M" : { } - } - } - ] -} diff --git a/examples/camp_examples/bright_chamber/use_case_7/wall_loss_rates_011519.txt b/examples/camp_examples/bright_chamber/use_case_7/wall_loss_rates_011519.txt deleted file mode 100644 index fa5182fa..00000000 --- a/examples/camp_examples/bright_chamber/use_case_7/wall_loss_rates_011519.txt +++ /dev/null @@ -1,6 +0,0 @@ -simtime; 0.0; 0.3; 0.6; 0.9; 1.2 -N2; 0.010; 0.012; 0.013; 0.014; 0.015 -O2; 0.015; 0.016; 0.017; 0.018; 0.019 -Ar; 0.015; 0.016; 0.017; 0.018; 0.019 -CO2; 0.010; 0.012; 0.013; 0.014; 0.015 -H2O; 0.010; 0.012; 0.013; 0.014; 0.015 diff --git a/examples/camp_examples/bright_chamber/use_case_8/camp_data/config.json b/examples/camp_examples/bright_chamber/use_case_8/camp_data/config.json deleted file mode 100644 index 4629149f..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/camp_data/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "camp-files" : [ - "camp_data/species.json", - "camp_data/mechanism.json" - ] -} diff --git a/examples/camp_examples/bright_chamber/use_case_8/camp_data/mechanism.json b/examples/camp_examples/bright_chamber/use_case_8/camp_data/mechanism.json deleted file mode 100644 index d3a78ae3..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/camp_data/mechanism.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "camp-data" : [ - { - "name" : "Chapman", - "type" : "MECHANISM", - "reactions" : [ - { - "type" : "EMISSION", - "species" : "O1D", - "MUSICA name" : "O1D" - }, - { - "type" : "EMISSION", - "species" : "O", - "MUSICA name" : "O" - }, - { - "type" : "EMISSION", - "species" : "O3", - "MUSICA name" : "O3" - }, - { - "type" : "EMISSION", - "species" : "N2", - "MUSICA name" : "N2" - }, - { - "type" : "EMISSION", - "species" : "Ar", - "MUSICA name" : "Ar" - }, - { - "type" : "EMISSION", - "species" : "O2", - "MUSICA name" : "O2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "N2", - "MUSICA name" : "N2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "O2", - "MUSICA name" : "O2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "CO2", - "MUSICA name" : "CO2" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "Ar", - "MUSICA name" : "Ar" - }, - { - "type" : "FIRST_ORDER_LOSS", - "species" : "H2O", - "MUSICA name" : "H2O" - } - ] - } - ] -} - diff --git a/examples/camp_examples/bright_chamber/use_case_8/camp_data/species.json b/examples/camp_examples/bright_chamber/use_case_8/camp_data/species.json deleted file mode 100644 index 948aca00..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/camp_data/species.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "camp-data" : [ - { - "type" : "RELATIVE_TOLERANCE", - "value" : 1.0e-4 - }, - { - "name" : "M", - "type" : "CHEM_SPEC", - "tracer type" : "CONSTANT" - }, - { - "name" : "Ar", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "CO2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "H2O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "N2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O1D", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O3", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - } - ] -} - diff --git a/examples/camp_examples/bright_chamber/use_case_8/emissions.csv b/examples/camp_examples/bright_chamber/use_case_8/emissions.csv deleted file mode 100644 index 2553005b..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/emissions.csv +++ /dev/null @@ -1,5 +0,0 @@ -time.hr, EMIS.O1D, EMIS.O, EMIS.O3 -0.0, 0.0, 0.0, 0.0 -0.2, 0.1, 0.05, 0.05 -1.0, 0.2, 0.1, 0.1 -1.5, 0.0, 0.0, 0.0 diff --git a/examples/camp_examples/bright_chamber/use_case_8/emit_all.csv b/examples/camp_examples/bright_chamber/use_case_8/emit_all.csv deleted file mode 100644 index 0f4445c6..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/emit_all.csv +++ /dev/null @@ -1,4 +0,0 @@ -time, EMIS.O, EMIS.O1D, EMIS.O3, EMIS.N2, EMIS.Ar, EMIS.O2 -0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0 -20.0, 2.0, 1.0, 1.0, 2.0, 1.0, 1.0 -30.0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0 diff --git a/examples/camp_examples/bright_chamber/use_case_8/initial.csv b/examples/camp_examples/bright_chamber/use_case_8/initial.csv deleted file mode 100644 index 98cf0ff3..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/initial.csv +++ /dev/null @@ -1,2 +0,0 @@ -CONC.O& CONC.O1D& CONC.O3 &CONC.N2& CONC.O2& CONC.Ar& CONC.CO2& ENV.temperature& ENV.pressure.atm -1.0e-7& 1.0e-6& 1.0e-4& 3.29e1& 8.84& 3.92e-1& 1.69e-2& 298.0& 1.0 diff --git a/examples/camp_examples/bright_chamber/use_case_8/parking_lot_photo_rates.nc b/examples/camp_examples/bright_chamber/use_case_8/parking_lot_photo_rates.nc deleted file mode 100644 index fd3ba0f24bff980ce285055bed05231a4a0a570d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 280640 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 diff --git a/examples/camp_examples/bright_chamber/use_case_8/use_case_8_config.json b/examples/camp_examples/bright_chamber/use_case_8/use_case_8_config.json deleted file mode 100644 index 77c4a885..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/use_case_8_config.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "box model options" : { - "grid" : "box", - "chemistry time step [min]" : 5.0, - "output time step [hr]" : 1.0, - "simulation length [hr]" : 2.5, - "simulation start" : { - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - }, - "initial conditions" : { - "initial.csv" : { - "delimiter" : "&", - "properties" : { - "CONC.O3" : { "variability" : "tethered" } - }, - "linear combinations" : { - "atomic oxygen" : { - "properties" : { - "CONC.O" : { }, - "CONC.O1D" : { } - }, - "scale factor" : 1.2 - } - } - } - }, - "evolving conditions" : { - "emissions.csv" : { - "properties" : { - "time.hr" : { - "shift first entry to" :{ - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - } - } - }, - "wall_loss_rates_011519.txt" : { - "delimiter" : ";", - "time axis" : "columns", - "properties" : { - "simtime" : { - "MusicBox name" : "time", - "units" : "hr", - "shift first entry to" :{ - "time zone" : "UTC-8", - "year" : 2020, - "month" : 6, - "day" : 10, - "hour" : 13 - } - }, - "*" : { - "MusicBox name" : "LOSS.*", - "units" : "min-1" - } - } - }, - "parking_lot_photo_rates.nc" : { - "time offset" : { "years" : 15 }, - "properties" : { - "*" : { "MusicBox name" : "PHOT.*" }, - "time" : { - "MusicBox name" : "time", - "shift first entry to" : { - "year" : 2020, - "month" : 1, - "day" : 1, - "time zone" : "UTC-8" - } - } - } - } - }, - "model components" : [ - { - "type" : "CAMP", - "configuration file" : "camp_data/config.json", - "override species" : { - "M" : { "mixing ratio mol mol-1" : 1.0 } - }, - "suppress output" : { - "M" : { } - } - } - ] -} diff --git a/examples/camp_examples/bright_chamber/use_case_8/wall_loss_rates_011519.txt b/examples/camp_examples/bright_chamber/use_case_8/wall_loss_rates_011519.txt deleted file mode 100644 index fa5182fa..00000000 --- a/examples/camp_examples/bright_chamber/use_case_8/wall_loss_rates_011519.txt +++ /dev/null @@ -1,6 +0,0 @@ -simtime; 0.0; 0.3; 0.6; 0.9; 1.2 -N2; 0.010; 0.012; 0.013; 0.014; 0.015 -O2; 0.015; 0.016; 0.017; 0.018; 0.019 -Ar; 0.015; 0.016; 0.017; 0.018; 0.019 -CO2; 0.010; 0.012; 0.013; 0.014; 0.015 -H2O; 0.010; 0.012; 0.013; 0.014; 0.015 diff --git a/examples/camp_examples/dark_chamber/use_case_1/camp_data/config.json b/examples/camp_examples/dark_chamber/use_case_1/camp_data/config.json deleted file mode 100644 index af4e8619..00000000 --- a/examples/camp_examples/dark_chamber/use_case_1/camp_data/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "camp-files" : [ - "camp_data/species.json" - ] -} diff --git a/examples/camp_examples/dark_chamber/use_case_1/camp_data/species.json b/examples/camp_examples/dark_chamber/use_case_1/camp_data/species.json deleted file mode 100644 index 948aca00..00000000 --- a/examples/camp_examples/dark_chamber/use_case_1/camp_data/species.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "camp-data" : [ - { - "type" : "RELATIVE_TOLERANCE", - "value" : 1.0e-4 - }, - { - "name" : "M", - "type" : "CHEM_SPEC", - "tracer type" : "CONSTANT" - }, - { - "name" : "Ar", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "CO2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "H2O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "N2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O1D", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O3", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - } - ] -} - diff --git a/examples/camp_examples/dark_chamber/use_case_1/use_case_1_config.json b/examples/camp_examples/dark_chamber/use_case_1/use_case_1_config.json deleted file mode 100644 index b1ae76a7..00000000 --- a/examples/camp_examples/dark_chamber/use_case_1/use_case_1_config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "box model options" : { - "grid" : "box", - "chemistry time step [min]" : 5.0, - "output time step [hr]" : 1.0, - "simulation length [hr]" : 2.5 - }, - "chemical species" : { - "N2" : { "initial value [mol m-3]" : 3.29e1 }, - "O2" : { "initial value [mol m-3]" : 8.84e0 }, - "Ar" : { "initial value [mol m-3]" : 3.92e-1 }, - "CO2" : { "initial value [mol m-3]" : 1.69e-2 }, - "O" : { "initial value [mol m-3]" : 1.0e-5 } - }, - "environmental conditions" : { - "temperature" : { "initial value [K]" : 298.0 }, - "pressure" : { "initial value [atm]" : 1.0 } - }, - "model components" : [ - { - "type" : "CAMP", - "configuration file" : "camp_data/config.json", - "override species" : { - "M" : { "mixing ratio mol mol-1" : 1.0 } - }, - "suppress output" : { - "M" : { } - } - } - ] -} - diff --git a/examples/camp_examples/dark_chamber/use_case_2/camp_data/config.json b/examples/camp_examples/dark_chamber/use_case_2/camp_data/config.json deleted file mode 100644 index af4e8619..00000000 --- a/examples/camp_examples/dark_chamber/use_case_2/camp_data/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "camp-files" : [ - "camp_data/species.json" - ] -} diff --git a/examples/camp_examples/dark_chamber/use_case_2/camp_data/species.json b/examples/camp_examples/dark_chamber/use_case_2/camp_data/species.json deleted file mode 100644 index 948aca00..00000000 --- a/examples/camp_examples/dark_chamber/use_case_2/camp_data/species.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "camp-data" : [ - { - "type" : "RELATIVE_TOLERANCE", - "value" : 1.0e-4 - }, - { - "name" : "M", - "type" : "CHEM_SPEC", - "tracer type" : "CONSTANT" - }, - { - "name" : "Ar", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "CO2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "H2O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "N2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O1D", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O3", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - } - ] -} - diff --git a/examples/camp_examples/dark_chamber/use_case_2/initial.csv b/examples/camp_examples/dark_chamber/use_case_2/initial.csv deleted file mode 100644 index f422d6fa..00000000 --- a/examples/camp_examples/dark_chamber/use_case_2/initial.csv +++ /dev/null @@ -1,2 +0,0 @@ -CONC.N2, CONC.O2, CONC.Ar, CONC.CO2, CONC.O, ENV.temperature, ENV.pressure -3.29e1, 8.84, 3.92e-1, 1.69e-2, 1.0e-5, 298.0, 1.0 diff --git a/examples/camp_examples/dark_chamber/use_case_2/use_case_2_config.json b/examples/camp_examples/dark_chamber/use_case_2/use_case_2_config.json deleted file mode 100644 index d6f6ed3d..00000000 --- a/examples/camp_examples/dark_chamber/use_case_2/use_case_2_config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "box model options" : { - "grid" : "box", - "chemistry time step [min]" : 5.0, - "output time step [hr]" : 1.0, - "simulation length [hr]" : 2.5 - }, - "initial conditions" : { - "initial.csv" : { - "properties" : { - "ENV.pressure" : { "units" : "atm" } - } - } - }, - "model components" : [ - { - "type" : "CAMP", - "configuration file" : "camp_data/config.json", - "override species" : { - "M" : { "mixing ratio mol mol-1" : 1.0 } - }, - "suppress output" : { - "M" : { } - } - } - ] -} diff --git a/examples/camp_examples/dark_chamber/use_case_3/camp_data/config.json b/examples/camp_examples/dark_chamber/use_case_3/camp_data/config.json deleted file mode 100644 index af4e8619..00000000 --- a/examples/camp_examples/dark_chamber/use_case_3/camp_data/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "camp-files" : [ - "camp_data/species.json" - ] -} diff --git a/examples/camp_examples/dark_chamber/use_case_3/camp_data/species.json b/examples/camp_examples/dark_chamber/use_case_3/camp_data/species.json deleted file mode 100644 index 948aca00..00000000 --- a/examples/camp_examples/dark_chamber/use_case_3/camp_data/species.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "camp-data" : [ - { - "type" : "RELATIVE_TOLERANCE", - "value" : 1.0e-4 - }, - { - "name" : "M", - "type" : "CHEM_SPEC", - "tracer type" : "CONSTANT" - }, - { - "name" : "Ar", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "CO2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "H2O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "N2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O1D", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O2", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - }, - { - "name" : "O3", - "type" : "CHEM_SPEC", - "absolute tolerance" : 1.0e-12 - } - ] -} - diff --git a/examples/camp_examples/dark_chamber/use_case_3/initial.csv b/examples/camp_examples/dark_chamber/use_case_3/initial.csv deleted file mode 100644 index d53e9b6d..00000000 --- a/examples/camp_examples/dark_chamber/use_case_3/initial.csv +++ /dev/null @@ -1,2 +0,0 @@ -CONC.N2& CONC.O2& CONC.Ar& CONC.CO2& CONC.O& ENV.temperature& ENV.pressure.atm -3.29e1& 8.84& 3.92e-1& 1.69e-2& 1.0e-5& 298.0& 1.0 diff --git a/examples/camp_examples/dark_chamber/use_case_3/use_case_3_config.json b/examples/camp_examples/dark_chamber/use_case_3/use_case_3_config.json deleted file mode 100644 index 26285c60..00000000 --- a/examples/camp_examples/dark_chamber/use_case_3/use_case_3_config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "box model options" : { - "grid" : "box", - "chemistry time step [min]" : 5.0, - "output time step [hr]" : 1.0, - "simulation length [hr]" : 2.5 - }, - "initial conditions" : { - "initial.csv" : { - "delimiter" : "&" - } - }, - "model components" : [ - { - "type" : "CAMP", - "configuration file" : "camp_data/config.json", - "override species" : { - "M" : { "mixing ratio mol mol-1" : 1.0 } - }, - "suppress output" : { - "M" : { } - } - } - ] -} diff --git a/src/acom_music_box/__init__.py b/src/acom_music_box/__init__.py index dec1591c..d6ee556f 100644 --- a/src/acom_music_box/__init__.py +++ b/src/acom_music_box/__init__.py @@ -19,3 +19,4 @@ from .evolving_conditions import EvolvingConditions from .music_box import MusicBox +import acom_music_box.examples as Examples \ No newline at end of file diff --git a/src/acom_music_box/examples/__init__.py b/src/acom_music_box/examples/__init__.py new file mode 100644 index 00000000..7f291987 --- /dev/null +++ b/src/acom_music_box/examples/__init__.py @@ -0,0 +1 @@ +from .examples import CarbonBond5, Chapman, FlowTube, Analytical \ No newline at end of file diff --git a/tests/configs/analytical_config/camp_data/config.json b/src/acom_music_box/examples/configs/analytical/camp_data/config.json similarity index 100% rename from tests/configs/analytical_config/camp_data/config.json rename to src/acom_music_box/examples/configs/analytical/camp_data/config.json diff --git a/tests/configs/analytical_config/camp_data/reactions.json b/src/acom_music_box/examples/configs/analytical/camp_data/reactions.json similarity index 100% rename from tests/configs/analytical_config/camp_data/reactions.json rename to src/acom_music_box/examples/configs/analytical/camp_data/reactions.json diff --git a/tests/configs/analytical_config/camp_data/species.json b/src/acom_music_box/examples/configs/analytical/camp_data/species.json similarity index 100% rename from tests/configs/analytical_config/camp_data/species.json rename to src/acom_music_box/examples/configs/analytical/camp_data/species.json diff --git a/tests/configs/analytical_config/evolving_conditions.csv b/src/acom_music_box/examples/configs/analytical/evolving_conditions.csv similarity index 100% rename from tests/configs/analytical_config/evolving_conditions.csv rename to src/acom_music_box/examples/configs/analytical/evolving_conditions.csv diff --git a/tests/configs/analytical_config/my_config.json b/src/acom_music_box/examples/configs/analytical/my_config.json similarity index 100% rename from tests/configs/analytical_config/my_config.json rename to src/acom_music_box/examples/configs/analytical/my_config.json diff --git a/tests/configs/chapman_config/camp_data/config.json b/src/acom_music_box/examples/configs/carbon_bond_5/camp_data/config.json similarity index 100% rename from tests/configs/chapman_config/camp_data/config.json rename to src/acom_music_box/examples/configs/carbon_bond_5/camp_data/config.json diff --git a/tests/configs/full_gas_phase_mechanism_config/camp_data/reactions.json b/src/acom_music_box/examples/configs/carbon_bond_5/camp_data/reactions.json similarity index 100% rename from tests/configs/full_gas_phase_mechanism_config/camp_data/reactions.json rename to src/acom_music_box/examples/configs/carbon_bond_5/camp_data/reactions.json diff --git a/tests/configs/full_gas_phase_mechanism_config/camp_data/species.json b/src/acom_music_box/examples/configs/carbon_bond_5/camp_data/species.json similarity index 100% rename from tests/configs/full_gas_phase_mechanism_config/camp_data/species.json rename to src/acom_music_box/examples/configs/carbon_bond_5/camp_data/species.json diff --git a/tests/configs/full_gas_phase_mechanism_config/initial_conditions.csv b/src/acom_music_box/examples/configs/carbon_bond_5/initial_conditions.csv similarity index 100% rename from tests/configs/full_gas_phase_mechanism_config/initial_conditions.csv rename to src/acom_music_box/examples/configs/carbon_bond_5/initial_conditions.csv diff --git a/tests/configs/full_gas_phase_mechanism_config/my_config.json b/src/acom_music_box/examples/configs/carbon_bond_5/my_config.json similarity index 100% rename from tests/configs/full_gas_phase_mechanism_config/my_config.json rename to src/acom_music_box/examples/configs/carbon_bond_5/my_config.json diff --git a/tests/configs/full_gas_phase_mechanism_config/camp_data/config.json b/src/acom_music_box/examples/configs/chapman/camp_data/config.json similarity index 100% rename from tests/configs/full_gas_phase_mechanism_config/camp_data/config.json rename to src/acom_music_box/examples/configs/chapman/camp_data/config.json diff --git a/tests/configs/chapman_config/camp_data/reactions.json b/src/acom_music_box/examples/configs/chapman/camp_data/reactions.json similarity index 100% rename from tests/configs/chapman_config/camp_data/reactions.json rename to src/acom_music_box/examples/configs/chapman/camp_data/reactions.json diff --git a/tests/configs/chapman_config/camp_data/species.json b/src/acom_music_box/examples/configs/chapman/camp_data/species.json similarity index 100% rename from tests/configs/chapman_config/camp_data/species.json rename to src/acom_music_box/examples/configs/chapman/camp_data/species.json diff --git a/tests/configs/chapman_config/evolving_conditions.csv b/src/acom_music_box/examples/configs/chapman/evolving_conditions.csv similarity index 100% rename from tests/configs/chapman_config/evolving_conditions.csv rename to src/acom_music_box/examples/configs/chapman/evolving_conditions.csv diff --git a/tests/configs/chapman_config/my_config.json b/src/acom_music_box/examples/configs/chapman/my_config.json similarity index 100% rename from tests/configs/chapman_config/my_config.json rename to src/acom_music_box/examples/configs/chapman/my_config.json diff --git a/tests/configs/wall_loss_config/camp_data/config.json b/src/acom_music_box/examples/configs/flow_tube/camp_data/config.json similarity index 100% rename from tests/configs/wall_loss_config/camp_data/config.json rename to src/acom_music_box/examples/configs/flow_tube/camp_data/config.json diff --git a/tests/configs/wall_loss_config/camp_data/reactions.json b/src/acom_music_box/examples/configs/flow_tube/camp_data/reactions.json similarity index 100% rename from tests/configs/wall_loss_config/camp_data/reactions.json rename to src/acom_music_box/examples/configs/flow_tube/camp_data/reactions.json diff --git a/tests/configs/wall_loss_config/camp_data/species.json b/src/acom_music_box/examples/configs/flow_tube/camp_data/species.json similarity index 100% rename from tests/configs/wall_loss_config/camp_data/species.json rename to src/acom_music_box/examples/configs/flow_tube/camp_data/species.json diff --git a/tests/configs/wall_loss_config/evolving_conditions.csv b/src/acom_music_box/examples/configs/flow_tube/evolving_conditions.csv similarity index 100% rename from tests/configs/wall_loss_config/evolving_conditions.csv rename to src/acom_music_box/examples/configs/flow_tube/evolving_conditions.csv diff --git a/tests/configs/wall_loss_config/initial_conditions.csv b/src/acom_music_box/examples/configs/flow_tube/initial_conditions.csv similarity index 100% rename from tests/configs/wall_loss_config/initial_conditions.csv rename to src/acom_music_box/examples/configs/flow_tube/initial_conditions.csv diff --git a/tests/configs/wall_loss_config/my_config.json b/src/acom_music_box/examples/configs/flow_tube/my_config.json similarity index 100% rename from tests/configs/wall_loss_config/my_config.json rename to src/acom_music_box/examples/configs/flow_tube/my_config.json diff --git a/src/acom_music_box/examples/examples.py b/src/acom_music_box/examples/examples.py new file mode 100644 index 00000000..ad15d216 --- /dev/null +++ b/src/acom_music_box/examples/examples.py @@ -0,0 +1,36 @@ +import os + +class Example: + def __init__(self, name, description, path): + self.name = name + self.description = description + self.path = path + + def __str__(self): + return f'{self.name}: {self.description}' + + def __repr__(self): + return f'{self.name}: {self.description}' + + @classmethod + def from_config(cls, display_name, folder_name, description): + path = os.path.join(os.path.dirname(__file__), 'configs', folder_name, 'my_config.json') + return cls(name=display_name, description=description, path=path) + +# Create instances +CarbonBond5 = Example.from_config( + display_name='Carbon Bond IV', + folder_name='carbon_bond_5', + description= 'Carbon bond 5') +Chapman= Example.from_config( + display_name='Chapman', + folder_name='chapman', + description= 'The Chapman cycle with conditions over Boulder, Colorado') +FlowTube = Example.from_config( + display_name='Flow Tube', + folder_name='flow_tube', + description= 'A fictitious flow tube experiment') +Analytical = Example.from_config( + display_name='Analytical', + folder_name='analytical', + description= 'An example of an analytical solution to a simple chemical system') \ No newline at end of file diff --git a/tests/test_analytical.py b/tests/test_analytical.py index c3eceb56..85da5dec 100644 --- a/tests/test_analytical.py +++ b/tests/test_analytical.py @@ -1,17 +1,20 @@ -from acom_music_box import MusicBox +from acom_music_box import MusicBox, Examples +import os import math - class TestAnalytical: def test_run(self): box_model = MusicBox() # configures box model - conditions_path = "configs/analytical_config/my_config.json" - camp_path = "configs/analytical_config/camp_data" - + conditions_path = Examples.Analytical.path box_model.readConditionsFromJson(conditions_path) + + camp_path = os.path.join( + os.path.dirname(conditions_path), + box_model.config_file) + box_model.create_solver(camp_path) # solves and saves output diff --git a/tests/test_full_gas_phase_mechanism.py b/tests/test_carbon_bond_5.py similarity index 91% rename from tests/test_full_gas_phase_mechanism.py rename to tests/test_carbon_bond_5.py index 2f104601..9ede8e16 100644 --- a/tests/test_full_gas_phase_mechanism.py +++ b/tests/test_carbon_bond_5.py @@ -1,18 +1,22 @@ -from acom_music_box import MusicBox +from acom_music_box import MusicBox, Examples +import os import csv import math -class TestFullGassPhaseMechanism: +class TestCarbonBond5: def test_run(self): box_model = MusicBox() # configures box model - conditions_path = "configs/full_gas_phase_mechanism_config/my_config.json" - camp_path = "configs/full_gas_phase_mechanism_config/camp_data" - + conditions_path = Examples.CarbonBond5.path box_model.readConditionsFromJson(conditions_path) + + camp_path = os.path.join( + os.path.dirname(conditions_path), + box_model.config_file) + box_model.create_solver(camp_path) # solves and saves output @@ -116,5 +120,5 @@ def test_run(self): if __name__ == "__main__": - test = TestFullGassPhaseMechanism() + test = TestCarbonBond5() test.test_run() diff --git a/tests/test_chapman.py b/tests/test_chapman.py index 58e06175..363f826e 100644 --- a/tests/test_chapman.py +++ b/tests/test_chapman.py @@ -1,4 +1,6 @@ -from acom_music_box import MusicBox +from acom_music_box import MusicBox, Examples + +import os import csv import math @@ -8,11 +10,13 @@ def test_run(self): box_model = MusicBox() # configures box model - conditions_path = "configs/chapman_config/my_config.json" - camp_path = "configs/chapman_config/camp_data" - + conditions_path = Examples.Chapman.path box_model.readConditionsFromJson(conditions_path) + camp_path = os.path.join( + os.path.dirname(conditions_path), + box_model.config_file) + box_model.create_solver(camp_path) # solves and saves output diff --git a/tests/test_wall_loss.py b/tests/test_flow_tube.py similarity index 88% rename from tests/test_wall_loss.py rename to tests/test_flow_tube.py index f269054b..fe293c4f 100644 --- a/tests/test_wall_loss.py +++ b/tests/test_flow_tube.py @@ -1,4 +1,5 @@ -from acom_music_box import MusicBox +from acom_music_box import MusicBox, Examples +import os import csv import math @@ -9,10 +10,13 @@ def test_run(self): box_model = MusicBox() # configures box model - conditions_path = "configs/wall_loss_config/my_config.json" - camp_path = "configs/wall_loss_config/camp_data" - + conditions_path = Examples.FlowTube.path box_model.readConditionsFromJson(conditions_path) + + camp_path = os.path.join( + os.path.dirname(conditions_path), + box_model.config_file) + box_model.create_solver(camp_path) # solves and saves output From 3f614571432903e4e5a21de30e42210e922ec539 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 23:48:17 -0500 Subject: [PATCH 05/11] adding examples --- src/acom_music_box/__init__.py | 2 +- src/acom_music_box/examples/__init__.py | 2 +- src/acom_music_box/examples/examples.py | 59 ++++++++++++++++--------- src/acom_music_box/main.py | 23 +++++++--- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/acom_music_box/__init__.py b/src/acom_music_box/__init__.py index d6ee556f..f7274688 100644 --- a/src/acom_music_box/__init__.py +++ b/src/acom_music_box/__init__.py @@ -19,4 +19,4 @@ from .evolving_conditions import EvolvingConditions from .music_box import MusicBox -import acom_music_box.examples as Examples \ No newline at end of file +from .examples import Examples \ No newline at end of file diff --git a/src/acom_music_box/examples/__init__.py b/src/acom_music_box/examples/__init__.py index 7f291987..cccf6e33 100644 --- a/src/acom_music_box/examples/__init__.py +++ b/src/acom_music_box/examples/__init__.py @@ -1 +1 @@ -from .examples import CarbonBond5, Chapman, FlowTube, Analytical \ No newline at end of file +from .examples import Examples \ No newline at end of file diff --git a/src/acom_music_box/examples/examples.py b/src/acom_music_box/examples/examples.py index ad15d216..b6e1a3db 100644 --- a/src/acom_music_box/examples/examples.py +++ b/src/acom_music_box/examples/examples.py @@ -1,8 +1,9 @@ import os class Example: - def __init__(self, name, description, path): + def __init__(self, name, short_name, description, path): self.name = name + self.short_name = short_name self.description = description self.path = path @@ -13,24 +14,42 @@ def __repr__(self): return f'{self.name}: {self.description}' @classmethod - def from_config(cls, display_name, folder_name, description): + def from_config(cls, display_name, folder_name, short_name, description): path = os.path.join(os.path.dirname(__file__), 'configs', folder_name, 'my_config.json') - return cls(name=display_name, description=description, path=path) + return cls(name=display_name, short_name = short_name, description=description, path=path) -# Create instances -CarbonBond5 = Example.from_config( - display_name='Carbon Bond IV', - folder_name='carbon_bond_5', - description= 'Carbon bond 5') -Chapman= Example.from_config( - display_name='Chapman', - folder_name='chapman', - description= 'The Chapman cycle with conditions over Boulder, Colorado') -FlowTube = Example.from_config( - display_name='Flow Tube', - folder_name='flow_tube', - description= 'A fictitious flow tube experiment') -Analytical = Example.from_config( - display_name='Analytical', - folder_name='analytical', - description= 'An example of an analytical solution to a simple chemical system') \ No newline at end of file +class _Examples: + CarbonBond5 = Example.from_config( + display_name='Carbon Bond IV', + short_name='CB5', + folder_name='carbon_bond_5', + description='Carbon bond 5') + Chapman = Example.from_config( + display_name='Chapman', + short_name='Chapman', + folder_name='chapman', + description='The Chapman cycle with conditions over Boulder, Colorado') + FlowTube = Example.from_config( + display_name='Flow Tube', + short_name='FlowTube', + folder_name='flow_tube', + description='A fictitious flow tube experiment') + Analytical = Example.from_config( + display_name='Analytical', + short_name='Analytical', + folder_name='analytical', + description='An example of an analytical solution to a simple chemical system') + + @classmethod + def get_all(cls): + return [cls.CarbonBond5, cls.Chapman, cls.FlowTube, cls.Analytical] + + def __iter__(self): + return iter(self.get_all()) + + def __getattr__(self, item): + if hasattr(self, item): + return getattr(self, item) + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'") + +Examples = _Examples() \ No newline at end of file diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index f1e848c2..cbb33e19 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -1,21 +1,29 @@ import os import argparse -from acom_music_box import MusicBox +from acom_music_box import MusicBox, Examples import datetime import sys import logging import colorlog +def format_examples_help(examples): + return '\n'.join(f"{e.short_name}: {e.description}" for e in examples) + def parse_arguments(): parser = argparse.ArgumentParser( description='MusicBox simulation runner.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter + formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument( '-c', '--config', type=str, - required=True, - help='Path to the configuration file.' + help='Path to the configuration file. If --example is provided, this argument is ignored.' + ) + parser.add_argument( + '-e', '--example', + type=str, + choices=[e.short_name for e in Examples], + help=f'Name of the example to use. Overrides --config.\nAvailable examples:\n{format_examples_help(Examples)}' ) parser.add_argument( '-o', '--output', @@ -69,7 +77,12 @@ def main(): logger.debug(f"Working directory = {os.getcwd()}") - musicBoxConfigFile = args.config + if args.example: + example = next(e for e in Examples if e.short_name == args.example) + musicBoxConfigFile = example.path + logger.info(f"Using example: {example}") + else: + musicBoxConfigFile = args.config musicBoxOutputPath = args.output From 5a130934e0caca167b404e31b53816bcc9b9a1d7 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 26 Aug 2024 23:53:37 -0500 Subject: [PATCH 06/11] updating CI tests --- .github/workflows/CI_Tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI_Tests.yml b/.github/workflows/CI_Tests.yml index 01bae148..e36a1b28 100644 --- a/.github/workflows/CI_Tests.yml +++ b/.github/workflows/CI_Tests.yml @@ -39,5 +39,8 @@ jobs: - name: Run the smoke tests run: | - music_box configFile=tests/configs/analytical_config/my_config.json outputDir=tests/configs/analytical_config + music_box -c src/acom_music_box/examples/configs/analytical_config/my_config.json -o output.csv + music_box -e Analytical -o output.csv + music_box -e Analytical -o output.csv -vv --color-output + From f713cfab1ff153e4b84a79452682fcbf70490fc6 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 27 Aug 2024 08:06:52 -0500 Subject: [PATCH 07/11] one more time --- .github/workflows/CI_Tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI_Tests.yml b/.github/workflows/CI_Tests.yml index e36a1b28..b789a186 100644 --- a/.github/workflows/CI_Tests.yml +++ b/.github/workflows/CI_Tests.yml @@ -39,7 +39,7 @@ jobs: - name: Run the smoke tests run: | - music_box -c src/acom_music_box/examples/configs/analytical_config/my_config.json -o output.csv + music_box -c src/acom_music_box/examples/configs/analytical/my_config.json -o output.csv music_box -e Analytical -o output.csv music_box -e Analytical -o output.csv -vv --color-output From 2e4bd0dcc6db29eae9db291dd8912746691574f4 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 27 Aug 2024 09:15:46 -0500 Subject: [PATCH 08/11] output csv to stdout --- pyproject.toml | 3 ++- src/acom_music_box/main.py | 2 +- src/acom_music_box/music_box.py | 13 ++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fd1b3964..9732f59a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,8 @@ dynamic = ["version", "description"] dependencies = [ "musica==0.7.3", - "colorlog" + "colorlog", + "pandas" ] [project.urls] diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index cbb33e19..1e79ad45 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -99,7 +99,7 @@ def main(): result = myBox.solve(musicBoxOutputPath) if musicBoxOutputPath is None: - print(result) + print(result.to_csv(index=False)) end = datetime.datetime.now() logger.info(f"End time: {end}") diff --git a/src/acom_music_box/music_box.py b/src/acom_music_box/music_box.py index 5cae95d0..14245bb7 100644 --- a/src/acom_music_box/music_box.py +++ b/src/acom_music_box/music_box.py @@ -8,6 +8,7 @@ from .evolving_conditions import EvolvingConditions import json import os +import pandas as pd import logging logger = logging.getLogger(__name__) @@ -551,8 +552,10 @@ def solve(self, output_path=None): # increments time curr_time += self.box_model_options.chem_step_time + df = pd.DataFrame(output_array[1:], columns=output_array[0]) # outputs to file if output is present if output_path is not None: + # Check if the output_path is a full path or just a file name if os.path.dirname(output_path) == '': # If output_path is just a filename, use the current directory @@ -564,14 +567,10 @@ def solve(self, output_path=None): dir_path = os.path.dirname(output_path) if dir_path and not os.path.exists(dir_path): os.makedirs(dir_path, exist_ok=True) - - # Write to the specified file path - with open(output_path, 'w', newline='') as output_file: - writer = csv.writer(output_file) - writer.writerows(output_array) - # returns output_array - return output_array + df.to_csv(output_path, index=False) + + return df def readFromUIJson(self, path_to_json): """ From 0b59a344cbe45fad428c3ad95409ee9c961a2d4b Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 27 Aug 2024 10:33:44 -0500 Subject: [PATCH 09/11] add logging if gnuplot is installed --- src/acom_music_box/main.py | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index 1e79ad45..fcd63858 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -5,6 +5,8 @@ import sys import logging import colorlog +import subprocess +import tempfile def format_examples_help(examples): return '\n'.join(f"{e.short_name}: {e.description}" for e in examples) @@ -41,6 +43,11 @@ def parse_arguments(): action='store_true', help='Enable color output for logs.' ) + parser.add_argument( + '--plot', + type=str, + help='Comma-separated list of species to plot (e.g., CONC.A,CONC.B).' + ) return parser.parse_args() def setup_logging(verbosity, color_output): @@ -64,6 +71,39 @@ def setup_logging(verbosity, color_output): console_handler.setFormatter(formatter) logging.basicConfig(level=log_level, handlers=[console_handler]) +def plot_with_gnuplot(data, species_list): + # Prepare columns and data for plotting + columns = ['time'] + species_list + data_to_plot = data[columns] + + data_csv = data_to_plot.to_csv(index=False) + + try: + with tempfile.NamedTemporaryFile(delete=False, suffix='.csv') as data_file: + data_file.write(data_csv.encode()) + data_file_path = data_file.name + + plot_commands = ',\n\t'.join(f"'{data_file_path}' using 1:{i+2} with lines title '{species}'" for i, species in enumerate(species_list)) + + gnuplot_command = f""" + set datafile separator ","; + set terminal dumb size 120,30; + set xlabel 'Time'; + set ylabel 'Value'; + set title 'Time vs Species'; + plot {plot_commands} + """ + + subprocess.run(['gnuplot', '-e', gnuplot_command], check=True) + except FileNotFoundError: + logging.critical("gnuplot is not installed. Skipping plotting.") + except subprocess.CalledProcessError as e: + logging.error(f"Error occurred while plotting: {e}") + finally: + # Clean up the temporary file + if data_file_path: + os.remove(data_file_path) + def main(): start = datetime.datetime.now() @@ -85,6 +125,7 @@ def main(): musicBoxConfigFile = args.config musicBoxOutputPath = args.output + plot_species_list = args.plot.split(',') if args.plot else None # Create and load a MusicBox object myBox = MusicBox() @@ -100,6 +141,10 @@ def main(): if musicBoxOutputPath is None: print(result.to_csv(index=False)) + + if plot_species_list: + # Prepare data for plotting + plot_with_gnuplot(result, plot_species_list) end = datetime.datetime.now() logger.info(f"End time: {end}") From 2a87fc47f52b5d2a503e0da9329d7470d8e8e592 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 27 Aug 2024 10:39:02 -0500 Subject: [PATCH 10/11] correcting tests --- src/acom_music_box/main.py | 2 +- tests/test_analytical.py | 3 ++- tests/test_carbon_bond_5.py | 3 ++- tests/test_chapman.py | 3 ++- tests/test_flow_tube.py | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index fcd63858..dfe70076 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -87,7 +87,7 @@ def plot_with_gnuplot(data, species_list): gnuplot_command = f""" set datafile separator ","; - set terminal dumb size 120,30; + set terminal dumb size 120,25; set xlabel 'Time'; set ylabel 'Value'; set title 'Time vs Species'; diff --git a/tests/test_analytical.py b/tests/test_analytical.py index 85da5dec..de0fd464 100644 --- a/tests/test_analytical.py +++ b/tests/test_analytical.py @@ -18,7 +18,8 @@ def test_run(self): box_model.create_solver(camp_path) # solves and saves output - output = box_model.solve() + df = box_model.solve() + output = [df.columns.values.tolist()] + df.values.tolist() conc_a_index = output[0].index("CONC.A") conc_b_index = output[0].index("CONC.B") diff --git a/tests/test_carbon_bond_5.py b/tests/test_carbon_bond_5.py index 9ede8e16..fdb82f01 100644 --- a/tests/test_carbon_bond_5.py +++ b/tests/test_carbon_bond_5.py @@ -20,7 +20,8 @@ def test_run(self): box_model.create_solver(camp_path) # solves and saves output - model_output = box_model.solve() + df = box_model.solve() + model_output = [df.columns.values.tolist()] + df.values.tolist() # read wall_loss_test.csv into test_output with open("expected_results/full_gas_phase_mechanism.csv", "r") as file: diff --git a/tests/test_chapman.py b/tests/test_chapman.py index 363f826e..765144da 100644 --- a/tests/test_chapman.py +++ b/tests/test_chapman.py @@ -20,7 +20,8 @@ def test_run(self): box_model.create_solver(camp_path) # solves and saves output - model_output = box_model.solve() + df = box_model.solve() + model_output = [df.columns.values.tolist()] + df.values.tolist() # read chapman_test.csv into test_output with open("expected_results/chapman_test.csv", "r") as file: diff --git a/tests/test_flow_tube.py b/tests/test_flow_tube.py index fe293c4f..7fff3148 100644 --- a/tests/test_flow_tube.py +++ b/tests/test_flow_tube.py @@ -20,7 +20,8 @@ def test_run(self): box_model.create_solver(camp_path) # solves and saves output - model_output = box_model.solve() + df = box_model.solve() + model_output = [df.columns.values.tolist()] + df.values.tolist() # read wall_loss_test.csv into test_output with open("expected_results/wall_loss_test.csv", "r") as file: From 8f686141a33c1b246b0299f763643dc4d11cacc1 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 27 Aug 2024 12:58:27 -0500 Subject: [PATCH 11/11] better argument description for plot --- src/acom_music_box/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/acom_music_box/main.py b/src/acom_music_box/main.py index dfe70076..e1baa9f8 100644 --- a/src/acom_music_box/main.py +++ b/src/acom_music_box/main.py @@ -46,7 +46,7 @@ def parse_arguments(): parser.add_argument( '--plot', type=str, - help='Comma-separated list of species to plot (e.g., CONC.A,CONC.B).' + help='Plot a comma-separated list of species if gnuplot is available (e.g., CONC.A,CONC.B).' ) return parser.parse_args()