#!/usr/bin/env python3 # # meteo_prof.py --- run HYSPLIT profile analysis # See HYSPLIT Tutorial Sec 4.3 # # Change history: # 17 Jun 2025 (BB) - initial, cross-platform version # 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 import subprocess from pathlib import Path if sys.version_info < (3,8): print("Please use Python 3.8 or higher.") sys.exit(1) # Detect OS and handle CLI args or fallback defaults system = platform.system().lower() if system == "windows": PGM = Path(sys.argv[1]) if len(sys.argv) >= 2 else Path("C:\\hysplit") OUT = Path(sys.argv[2]) if len(sys.argv) >= 3 else PGM / "working" TTR = Path(os.environ.get("TTR", "C:\\Tutorial")) exe_suffix = ".exe" else: PGM = Path(sys.argv[1]) if len(sys.argv) >= 2 else Path.home() / "hysplit" OUT = Path(sys.argv[2]) if len(sys.argv) >= 3 else PGM / "working" TTR = Path(os.environ.get("TTR", Path.home() / "Tutorial")) exe_suffix = "" # Verify required paths if not PGM.exists(): script = Path(__file__).name if "__file__" in globals() else "meteo_prof.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: Tutorial directory 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_TOTURIAL_DIRECTORY' For Linux users (csh or tcsh shell): setenv TTR 'YOUR_HYSPLIT_TOTURIAL_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) # Set parameters lat, lon = 39.90, -84.22 off, inc = 12, 6 met = TTR / "captex" dat = "captex2_wrf27uw.bin" met_file = met / dat if not met_file.exists(): print(f"ERROR: Meteorological file not found: {met_file}") sys.exit(1) profile_exe = PGM / "exec" / f"profile{exe_suffix}" profile_txt = OUT / "profile.txt" if not profile_exe.exists(): print(f"ERROR: profile executable not found at {profile_exe}") sys.exit(1) # Run profile.exe cmd = [ str(profile_exe), f"-d{met}{os.sep}", f"-f{dat}", f"-y{lat}", f"-x{lon}", f"-o{off}", f"-t{inc}", ] run_cmd(cmd, "Running HYSPLIT profile analysis") # Output results if profile_txt.exists(): print("\nProfile Output:\n" + "=" * 50) print(profile_txt.read_text(encoding="ascii")) else: print("Warning: profile.txt not found. Check HYSPLIT execution and inputs.")