Source code for qm_atlas.wrappers.macromodel.utils
import logging
from pathlib import Path
from qm_atlas.software_environment import SOFTWARE_CONFIG
from qm_atlas.utils import open_utf8
from qm_atlas.wrappers.common import run_command
_logger = logging.getLogger(__name__)
# Substrings that point to a likely cause of an empty/missing Macromodel output.
MACROMODEL_ERROR_INDICATORS = (
"Maximum conformation storage exceeded",
"PROTMP",
"AUTO SERIAL",
"license",
"FATAL",
"ERROR",
)
[docs]
def log_macromodel_errors(scr: Path) -> None:
"""Scan the Macromodel log files in a scratch directory for known error
indicators and log a plausible reason for a failed conformer generation.
Args:
scr (Path): The scratch directory containing the Macromodel log files.
"""
log_files = sorted(scr.glob("*.log"))
if not log_files:
_logger.error(f"No Macromodel log file found in {scr} to diagnose the failure")
return
found_indicator = False
storage_exceeded = False
for log_file in log_files:
try:
with open_utf8(log_file, "r") as f:
lines = f.readlines()
except OSError:
continue
for line in lines:
stripped = line.strip()
if any(ind.lower() in stripped.lower() for ind in MACROMODEL_ERROR_INDICATORS):
_logger.error(f"{log_file.name}: {stripped}")
found_indicator = True
if "Maximum conformation storage exceeded" in stripped:
storage_exceeded = True
if storage_exceeded:
_logger.error(
"Macromodel exceeded its internal conformer storage limit. This happens "
"when the search finds more conformers than 'max_conformers'. The output "
"stage then fails. Try increasing the 'max_conformers' option."
)
if not found_indicator:
_logger.error("Could not identify a specific error in the Macromodel log files")
[docs]
def convert_to_mae(
sdf_file: Path,
):
"""Convert an SDF file to Schrödinger .mae format via MacroModel's structconvert."""
software_env_manager = SOFTWARE_CONFIG.get_environment_manager()
str_conv = software_env_manager.get_command("macromodel", "structconvert")
mae_file = sdf_file.with_suffix(".mae")
command = f"{str_conv} {sdf_file} {mae_file}"
env = software_env_manager.get_run_environment("macromodel")
_, stderr = run_command(command, env=env)
if stderr:
_logger.error(f"Error converting to mae file: {stderr}")
if not mae_file.is_file():
_logger.error("Structure Conversion produced no .mae file")
raise RuntimeError("Structure Conversion produced no .mae file")
return mae_file