#!/usr/bin/env python3 # # src_coef.py --- Solving the Coefficient Matrix # See HYSPLIT Tutorial Sec. 13.6 # # Change history: # 18 Oct 2025 (BB) - standard-aligned, cross-platform version # 12 Feb 2026 (SZ) - minor edits for style consistency # 18 Jun 2026 (SZ) - standardize code for run_cmd(), convert_html_to_img(), # etc. across Python scripts # - ensure encoding is specified when opening files import os import sys import platform from pathlib import Path import subprocess if sys.version_info < (3, 8): print("Please use Python 3.8 or higher.") sys.exit(1) system = platform.system().lower() if system == "windows": PGM = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("C:\\hysplit") OUT = Path(sys.argv[2]) if len(sys.argv) > 2 else PGM / "working" DSP = sys.argv[3] if len(sys.argv) > 3 else "YES" TTR = Path(os.environ.get("TTR", "C:\\Tutorial")) exe_suffix = ".exe" else: PGM = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.home() / "hysplit" OUT = Path(sys.argv[2]) if len(sys.argv) > 2 else PGM / "working" DSP = sys.argv[3] if len(sys.argv) > 3 else "YES" TTR = Path(os.environ.get("TTR", Path.home() / "tutorial")) exe_suffix = "" if not PGM.exists(): script = Path(__file__).name if "__file__" in globals() else "src_coef.py" print(f"ERROR: HYSPLIT not found at {PGM}") print(f""" Please specify the path to your HYSPLIT installation using a command-line argument: python {script} YOUR_HYSPLIT_DIRECTORY [OUT] [DSP (YES|NO)] Example: python {script} C:\\hysplit C:\\hysplit\\working YES """) sys.exit(1) if not TTR.exists(): print(f"ERROR: HYSPLIT tutorial not found at {TTR}") print(""" Please set the TTR environment variable to point to your HYSPLIT tutorial directory. For Windows users (Command Prompt): SET TTR=YOUR_HYSPLIT_TUTORIAL_DIRECTORY For Linux users (bash shell): export TTR='YOUR_HYSPLIT_TUTORIAL_DIRECTORY' For Linux users (csh or tcsh shell): setenv TTR 'YOUR_HYSPLIT_TUTORIAL_DIRECTORY'""") sys.exit(1) os.chdir(OUT) # ------------------------------------------------------------------ # Helper function # ------------------------------------------------------------------ def run_cmd(cmd, desc="", allow_fail=False, stdout_file=None, append=False): if desc: print(f"{desc}...") exitcode = 0 with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) as p: if stdout_file: mode="a" if append else "w" with open(stdout_file, mode, encoding="utf-8") as f_out: for ln in p.stdout: print(ln, end="") f_out.write(ln) else: with p.stdout as f: for ln in iter(f.readline, b'\n'): if len(ln) == 0: break print(ln.rstrip()) done = False while not done: try: exitcode = p.wait(timeout=1) done = True except subprocess.TimeoutExpired: print("WARN: subprocess timed out.") if exitcode != 0: if allow_fail: print(f"WARN: command failed with exit code {exitcode} -> {' '.join(cmd)}") else: print(f"ERROR: command failed with exit code {exitcode} -> {' '.join(cmd)}") sys.exit(1) # ------------------------------------------------------------------- # constants # ------------------------------------------------------------------- wrk = TTR met_dir = wrk / "captex" met_file = "RP198309.gbl" lat = 43.0 lon = -75.0 lvl = 10.0 top = 10000.0 # ------------------------------------------------------------------- # ASCDATA.CFG # ------------------------------------------------------------------- with open("ASCDATA.CFG", "w", encoding="ascii") as f: f.write( "-90.0 -180.0\n" "1.0 1.0\n" "180 360\n" "2\n" "0.2\n" f"'{PGM / 'bdyfiles'}{os.sep}' directory of files\n" ) # ------------------------------------------------------------------- # SETUP.CFG # ------------------------------------------------------------------- with open("SETUP.CFG", "w", encoding="ascii") as f: f.write("&SETUP\n") f.write(" numpar = 10000,\n") f.write(" maxpar = 20000,\n") f.write("/\n") # ------------------------------------------------------------------- # remove old INFILE # ------------------------------------------------------------------- Path("INFILE").unlink(missing_ok=True) # ------------------------------------------------------------------- # build coefficient matrix runs # ------------------------------------------------------------------- run_hours = 72 for day in ("01", "02", "03"): for hour in ("00", "12"): run_hours -= 12 tag = f"tcm09{day}{hour}" with open("CONTROL", "w", encoding="ascii") as f: f.write(f"83 09 {day} {hour}\n") f.write("1\n") f.write(f"{lat} {lon} {lvl}\n") f.write(f"{run_hours}\n") f.write("0\n") f.write(f"{top}\n") f.write("1\n") f.write(f"{met_dir}{os.sep}\n") f.write(f"{met_file}\n") f.write("1\n") f.write("PMCH\n") f.write("1.0\n") f.write("12.0\n") f.write("00 00 00 00 00\n") f.write("1\n") f.write("41.0 -73.0\n") f.write("0.10 0.10\n") f.write("15.0 25.0\n") f.write(f".{os.sep}\n") f.write(f"{tag}\n") f.write("1\n") f.write("100\n") f.write("83 09 01 00 00\n") f.write("83 09 03 12 00\n") f.write("00 03 00\n") f.write("1\n") f.write("0.0 0.0 0.0\n") f.write("0.0 0.0 0.0 0.0 0.0\n") f.write("0.0 0.0 0.0\n") f.write("0.0\n") f.write("0.0\n") Path(tag).unlink(missing_ok=True) if run_hours >= 12: run_cmd([str(PGM / "exec" / f"hycs_std{exe_suffix}")]) with open("INFILE", "a", encoding="ascii") as f: f.write(f"{tag}\n") # ------------------------------------------------------------------- # coefficient array # ------------------------------------------------------------------- Path("c2array.txt").unlink(missing_ok=True) run_cmd([ str(PGM / "exec" / f"c2array{exe_suffix}"), "-c1.0E+12", "-iINFILE", f"-m{met_dir}{os.sep}hypo_meas.txt", "-oc2array.csv" ]) with open("c2array.csv", "r", encoding="ascii", errors="ignore") as f: print(f.read()) if DSP.upper() == "YES": input("Press Enter to continue...") # ------------------------------------------------------------------- # solve coefficient matrix # ------------------------------------------------------------------- run_cmd([ str(PGM / "exec" / f"tcsolve{exe_suffix}"), "-ic2array.csv", "-otcsolve.dat", "-z0.0" ]) with open("tcsolve.dat", "r", encoding="ascii", errors="ignore") as f: print(f.read())