Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pyqmmm/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ def md(
@click.option("--bond_valence", "-bv", is_flag=True, help="Replace QM optimized atoms in a pdb.")
@click.option("--orca_scan", "-os", is_flag=True, help="Plots an ORCA scan.")
@click.option("--orca_neb_restart", "-rneb", is_flag=True, help="Prepare to restart an ORCA NEB.")
@click.option("--orca_clean_irc", "-circ", is_flag=True, help="Removes remaining files from an IRC calc.")
@click.option("--combine_nebs", "-cneb", is_flag=True, help="Combines and NEBs.")
@click.option("--plot_combine_nebs", "-pcneb", is_flag=True, help="Combines and plots NEBs as a single trajectory.")
@click.option("--extract_energies", "-ee", is_flag=True, help="Extract electronic energies")
Expand All @@ -296,6 +297,7 @@ def qm(
bond_valence,
orca_scan,
orca_neb_restart,
orca_clean_irc,
combine_nebs,
plot_combine_nebs,
extract_energies,
Expand Down Expand Up @@ -371,6 +373,10 @@ def qm(
files_in_directory = [f for f in os.listdir() if f != 'delete']
pyqmmm.qm.orca_neb_restart.move_files(files_in_directory)

if orca_clean_irc:
import pyqmmm.qm.orca_clean_irc
pyqmmm.qm.orca_clean_irc.main()

if combine_nebs:
import pyqmmm.qm.combine_nebs
pyqmmm.qm.combine_nebs.combine_trajectories()
Expand Down
99 changes: 99 additions & 0 deletions pyqmmm/qm/orca_clean_irc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""
orca_irc_cleanup.py
===================

Utility to purge non‑essential files left over from an ORCA **I**ntrinsic **R**eaction **C**oordinate (IRC) job.

Safety features
---------------
1. **IRC verification** – The script aborts unless **at least one** ``*.out`` file in the working directory
contains the phrase ``"Storing full IRC trajectory in"`` (case‑sensitive), which ORCA prints only for
IRC runs.
2. **Interactive confirmation** – A simple "Continue? (y/N):" prompt; default is **No**.
3. **Scope limited to CWD** – Only files directly in the current working directory are affected.

Examples
--------
$ cd /path/to/irc_job # <- run inside the job dir
$ python orca_irc_cleanup.py
Identified 8 left over files from the IRC calculation. Continue? (y/N): y
Deleted 8 files.
"""
from __future__ import annotations

import os
import sys
from pathlib import Path
from typing import List, Set

ALLOWED_EXTS: Set[str] = {
".sh", ".out", ".in", ".gbw", ".xyz", ".densities", ".densitiesinfo", ".engrad",
}

MARKER = "Storing full IRC trajectory in"


def is_irc_directory(path: Path) -> bool:
"""Return *True* if any ``*.out`` file under *path* contains ``MARKER``.

Parameters
----------
path
Directory expected to hold ORCA output files.

Notes
-----
Reads files line‑by‑line and stops at the first match.
"""
for out_file in path.glob("*.out"):
try:
with out_file.open("r", errors="ignore") as f:
for line in f:
if MARKER in line:
return True
except OSError:
continue # unreadable file – just skip
return False


def find_leftovers(path: Path) -> List[Path]:
"""Return list of files lacking extensions in ``ALLOWED_EXTS``."""
return [p for p in path.iterdir() if p.is_file() and p.suffix.lower() not in ALLOWED_EXTS]


def main() -> None: # noqa: D401
"""Script entry point."""
cwd = Path(".").resolve()

if not is_irc_directory(cwd):
sys.exit("This directory does not appear to be an ORCA IRC calculation (marker not found).")

leftovers = find_leftovers(cwd)
count = len(leftovers)
if count == 0:
print("No extraneous files found. Nothing to do.")
return

print(f"You are located in: {os.getcwd()}")
response = input(
f"Identified {count} left over file{'s' if count != 1 else ''} from the IRC calculation. "
"Continue? (y/N): "
).strip().lower()
if response != "y":
print("Aborted.")
return

deleted = 0
for fp in leftovers:
try:
fp.unlink()
deleted += 1
except Exception as exc:
print(f"Could not delete {fp}: {exc}", file=sys.stderr)

print(f"Deleted {deleted} file{'s' if deleted != 1 else ''}.")


if __name__ == "__main__":
main()
Loading