Write a Python Run Script
In this discussion, we will examine the development of a Python Run Script (PRS). Firstly, a thorough list of requirements will be outlined. Following this, all available support tools will be introduced.
PRS Requirements
A PRS must be a callable script. Ideally, this can is a Python file that has a
if __name__ == '__main__':
...
block or at least executable code if the script is called as Python.
A PRS is a script that must accepts two arguments: the input file path and the output file path. Please refer to the Run Scripts document for information on the file formats of the output and input files.
The development should be completed to the point where it can support Python versions greater than 3.12.
Available support
ChemDoE is able to provide assistance with the development of a PRS. In order to use the assistance, it is necessary to install the PyPI package of ChemDoE (See How to run it.).
1. Pytests
Let us assume you have a script ‘main.py’
import sys
def read_input(path):
...
def calculate_variations(doe_table):
...
def write_output(variation_table, out_path):
...
if __name__ == '__main__':
doe_table = read_input(sys.argv[1])
variation_table = calculate_variations(doe_table)
write_output(variation_table, sys.argv[2])
then you can use the test assistance if you make a ‘test.py’
from json import JSONDecodeError
from ChemDoE.registery import check_doe_script
@check_doe_script('json', 'json')
def test_creat_script():
import main
project/
├──
├── src/
│ ├── main.py
│ ├── tests.py
├── README.md
├── setup.py
2. Register PRS programmatically
The configuration of a PRS can be facilitated through the utilisation of a GUI (Graphical User Interface). Alternatively, to facilitate this process, a PRS can also be configured/reorganised programmatically.
from ChemDoE.registration import register_python_doe_script
register_python_doe_script('main', 'json', 'json')
This code segment is intended to register a configuration entry in the ChemDoE, provided that the main script returns a correct result.
project/
├──
├── src/
│ ├── main.py
│ ├── tests.py
│ ├── register.py
├── README.md
├── setup.py
3. Register PRS from console
Alternatively to the registration of the PRS programmatically it is possible to use the CLI command of the ChemDoE:
ChemDoE add_python_script -src "/full/path/to/main.py" -i json -o json
Simple examples
import json # Import JSON module to read and write JSON files
import random
import sys # Import sys to access command-line arguments
# Define the number of variations to generate
NUMBER_OF_VARIATIONS = 11
print(f'Generating {NUMBER_OF_VARIATIONS} random variables')
# Read the input JSON file passed as the first command-line argument
print(f'Reading {sys.argv[1]}')
with open(sys.argv[1]) as jsonfile:
values = json.loads(jsonfile.read()) # Load JSON content into a dictionary
# Calculate context-related values
print(f'Calculating context')
row_count = len(values) # Total number of keys (variables) in the JSON data
number_of_options = len(values[list(values.keys())[0]]) - 1 # Number of options per variable (excluding unit)
print('Number of variables: ' + str(row_count))
print('Number of values per row: ' + str(number_of_options))
# Initialize results dictionary with VARIABLE and UNIT lists
results = {'VARIABLE': [], 'UNIT': []}
# Populate VARIABLE and UNIT lists with keys and corresponding unit values
for r_i, r_v in values.items():
results['VARIABLE'].append(r_i) # Store the variable name (key)
results['UNIT'].append(r_v[0]) # Store the unit (first element of the value list)
# Generate variations and store them in the results dictionary
print(f'Preparing Variations')
for i in range(NUMBER_OF_VARIATIONS):
results[f'Variation.{i}'] = [] # Initialize a new list for each variation
for r_i, r_v in enumerate(values.values()):
# Select a variation value based on computed index
results[f'Variation.{i}'].append(random.choice(r_v[1:]))
# Write the results to the output JSON file
print(f'Writing {sys.argv[2]}')
with open(sys.argv[2], 'w+') as json_file:
json_file.write(json.dumps(results, indent=4)) # Convert dictionary to JSON and write to file
import csv # Import the CSV module to read and write CSV files
import random
import sys # Import sys to access command-line arguments
# Define the number of variations to generate
NUMBER_OF_VARIATIONS = 11
print(f'Generating {NUMBER_OF_VARIATIONS} random variables')
# List to store the CSV data
values = []
# Read the input CSV file passed as the first command-line argument
print(f'Reading {sys.argv[1]}')
with open(sys.argv[1]) as csvfile:
reader = csv.reader(csvfile) # Create a CSV reader object
for row in reader:
values.append(list(row)) # Convert each row to a list and store it
# Calculate context-related values
print(f'Calculating context')
row_count = len(values) # Total number of rows in the CSV
number_of_options = len(values[0]) - 2 # Number of available options per column (excluding first two columns)
print('Number of variables: ' + str(row_count))
print('Number of values per row: ' + str(number_of_options))
# Initialize results dictionary with VARIABLE and UNIT lists
# Initialize results list with headers and units
# [
# [VARIABLE, UNIT, Variation.1, Variation.2, ...] First Row
# [S:xx, mol, 0.1, 0.2, ...] Second Row
# ... ... nth row
# ]
results = [['VARIABLE', 'UNIT']] + [[row[0], row[1]] for i, row in enumerate(values)]
# Generate variations and store them in the results list
print(f'Preparing Variations')
for i in range(NUMBER_OF_VARIATIONS):
results[0].append(f'Variation.{i}') # Append variation headers
for r_i in range(row_count):
# Select a variation value based on a random choice
results[r_i + 1].append(random.choice(values[r_i][2:]))
# Write the results to the output CSV file
print(f'Writing {sys.argv[2]}')
with open(sys.argv[2], 'w+') as csvfile:
csvfile.write('\n'.join((','.join(row) for row in results))) # Format and write CSV content