#!/usr/bin/env python
"""Command line utility to run amber antechamber command with AiiDA.
Usage: aiida_antechamber --help
"""
import os
import click
from aiida import cmdline, engine
from aiida.orm import SinglefileData
from aiida.plugins import CalculationFactory, DataFactory
from aiida_amber import helpers
# from aiida_amber.utils import searchprevious
[docs]
def launch(params):
"""Run antechamber.
Uses helpers to add amber on localhost to AiiDA on the fly.
- get inputs and outputs
- check if they are files
- add them as nodes
"""
# Prune unused CLI parameters from dict.
params = {k: v for k, v in params.items() if v is not None}
# dict to hold our calculation data.
inputs = {
"metadata": {
"description": params.pop("description"),
},
}
# If code is not initialised, then setup.
if "code" in inputs:
inputs["code"] = params.pop("code")
else:
computer = helpers.get_computer()
inputs["code"] = helpers.get_code(entry_point="antechamber", computer=computer)
# Prepare input parameters in AiiDA formats.
inputs["input_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("i"))
)
if "cf" in params:
inputs["charge_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("cf"))
)
if "a" in params:
inputs["additional_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("a"))
)
if "rf" in params:
inputs["res_top_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("rf"))
)
if "ch" in params:
inputs["check_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("ch"))
)
if "ge" in params:
inputs["esp_file"] = SinglefileData(
file=os.path.join(os.getcwd(), params.pop("ge"))
)
AntechamberParameters = DataFactory("amber.antechamber")
inputs["parameters"] = AntechamberParameters(params)
# need to search previous processes properly
# check if inputs are outputs from prev processes
# inputs = searchprevious.append_prev_nodes(inputs, inputs["input_list"])
# check if a pytest test is running, if so run rather than submit aiida job
# Note: in order to submit your calculation to the aiida daemon, do:
# pylint: disable=unused-variable
if "PYTEST_CURRENT_TEST" in os.environ:
future = engine.run(CalculationFactory("amber.antechamber"), **inputs)
else:
future = engine.submit(CalculationFactory("amber.antechamber"), **inputs)
@click.command()
@cmdline.utils.decorators.with_dbenv()
@cmdline.params.options.CODE()
# Plugin options
@click.option(
"--description",
default="record antechamber data provenance via the aiida_amber plugin",
type=str,
help="Short metadata description",
)
# Required inputs
@click.option("-i", default="input.mol2", type=str, help="input file name") # file
@click.option("-fi", default="mol2", type=str, help="input file format") # parameter
# Required outputs
@click.option("-o", default="output.mol2", type=str, help="output file name") # file
@click.option("-fo", default="mol2", type=str, help="output file format") # parameter
# optional input files
@click.option(
"-cf",
type=str,
help="charge file name",
)
@click.option(
"-a",
type=str,
help="additional file name",
)
@click.option(
"-rf",
type=str,
help="residue toplogy file name in prep input file, default is molecule.res",
)
@click.option(
"-ch",
type=str,
help="check file name for gaussian, default is 'molecule'",
)
@click.option(
"-ge",
type=str,
help="gaussian esp file generated by iop(6/50=1), default is g09.gesp",
)
# other parameters
@click.option(
"-c",
type=str,
help="charge method",
)
@click.option(
"-nc",
type=int,
help="net molecular charge (int)",
)
@click.option(
"-fa",
type=str,
help="additional file format",
)
@click.option(
"-ao",
type=str,
help="""additional file operation
crd : only read in coordinate
crg : only read in charge
radius: only read in radius
name : only read in atom name
type : only read in atom type
bond : only read in bond type""",
)
@click.option(
"-m",
type=str,
help="multiplicity (2S+1), default is 1",
)
@click.option(
"-rn",
type=str,
help="residue name, overrides input file, default is MOL",
)
@click.option(
"-ek",
type=str,
help="mopac or sqm keyword, inside quotes; overwrites previous ones",
)
@click.option(
"-gk",
type=str,
help="gaussian job keyword, inside quotes, is ignored when both -gopt and -gsp are used",
)
@click.option(
"-gopt",
type=str,
help="gaussian job keyword for optimization, inside quotes",
)
@click.option(
"-gsp",
type=str,
help="gaussian job keyword for single point calculation, inside quote",
)
@click.option(
"-gm",
type=str,
help='gaussian memory keyword, inside quotes, such as "%mem=1000MB"',
)
@click.option(
"-gn",
type=str,
help='gaussian number of processors keyword, inside quotes, such as "%nproc=8"',
)
@click.option(
"-gdsk",
type=str,
help='gaussian maximum disk usage keyword, inside quotes, such as "%maxdisk=50GB"',
)
@click.option(
"-gv",
type=int,
help="""add keyword to generate gesp file (for Gaussian 09 only)
1 : yes
0 : no, the default""",
)
@click.option(
"-tor",
type=str,
help="""torsional angle list, inside a pair of quotes, such as "1-2-3-4:0,5-6-7-8"
':1' or ':0' indicates the torsional angle is frozen or not""",
)
@click.option(
"-df",
type=int,
help="am1-bcc precharge flag, 2 - use sqm(default); 0 - use mopac",
)
@click.option(
"-at",
type=str,
help="""atom type
gaff : the default
gaff2: for gaff2 (beta-version)
amber: for PARM94/99/99SB
bcc : bcc
sybyl: sybyl """,
)
@click.option(
"-du",
type=str,
help="fix duplicate atom names: yes(y)[default] or no(n)",
)
@click.option(
"-bk",
type=str,
help="component/block Id, for ccif",
)
@click.option(
"-an",
type=str,
help="""adjust atom names: yes(y) or no(n)
the default is 'y' for 'mol2' and 'ac' and 'n' for the other formats""",
)
@click.option(
"-j",
type=int,
help="""atom type and bond type prediction index, default is 4
0 : no assignment
1 : atom type
2 : full bond types
3 : part bond types
4 : atom and full bond type
5 : atom and part bond type """,
)
@click.option(
"-s",
type=int,
help="status information: 0(brief), 1(default) or 2(verbose)",
)
@click.option(
"-eq",
type=int,
help="""equalizing atomic charge, default is 1 for '-c resp' and '-c bcc' and 0 for the other charge methods
0 : no use
1 : by atomic paths
2 : by atomic paths and structural information, i.e. E/Z configurations""",
)
@click.option(
"-pf",
type=str,
help="remove intermediate files: yes(y) or no(n)[default]",
)
@click.option(
"-pl",
type=str,
help="""maximum path length to determin equivalence of atomic charges for resp and bcc,
the smaller the value, the faster the algorithm, default is -1 (use full length),
set this parameter to 10 to 30 if your molecule is big (# atoms >= 100)""",
)
@click.option(
"-seq",
type=str,
help="atomic sequence order changable: yes(y)[default] or no(n)",
)
@click.option(
"-dr",
type=str,
help="acdoctor mode: yes(y)[default] or no(n)",
)
def cli(*args, **kwargs):
# pylint: disable=unused-argument
# pylint: disable=line-too-long
"""Run example.
Example usage:
$ aiida_antechamber --code antechamber@localhost -i input.mol2 -o output.mol2 -fi mol2 -fo mol2 -c bcc -pf yes -nc -2 -at gaff2 -j 5
Alternative (automatically tried to create amber@localhost code, but requires
amber to be installed and available in your environment path):
$ aiida_antechamber -i input.mol2 -o output.mol2 -fi mol2 -fo mol2 -c bcc -pf yes -nc -2 -at gaff2 -j 5
Help: $ aiida_antechamber --help
"""
launch(kwargs)
if __name__ == "__main__":
cli() # pylint: disable=no-value-for-parameter