-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bundles templats and allow coordgen to run without maeparser.
Now templates are always bundled into the coordgen library, so there is no search on the file system. coordgen can also be built without maeparser support (USE_MAEPARSER=OFF). This disables user-local template files, but it allows coordgen to be built without reliance on the maeparser library (and therefore without boost). This is useful for a couple of reasons: * We definitely see bugs in template discovery * 3rd party packagers seem to have trouble with building maeparser. * Allow use in other novel places that can't use the boost:: infrastructure required by maeparser. maeparser is always required for running the unit tests. Includes a short Python script for generating the C++ files describing the templates. This Python script currently requires use of the Schrodinger Python tools, so it will need to be manually updated if the templates are updated. There is a test that will fail if a new template is added but isn't added to the compiled templates. run it like: $SCHRODINGER/run mol_generator.py templates.mae
- Loading branch information
Showing
8 changed files
with
379 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
""" | ||
Using the schrodinger Python modules, read a template .mae file to | ||
generate the coordgen template C++ files. | ||
""" | ||
|
||
import sys | ||
import os | ||
import textwrap | ||
import argparse | ||
import subprocess | ||
|
||
from schrodinger import structure | ||
|
||
NAME = 'CoordgenTemplates' | ||
|
||
# String that creates a molecule and adds it to a container | ||
# of sketcherMinimizerMolecule* at index i. | ||
# | ||
# C++ programmers: `{` and `}` are escaped by duplication, so | ||
# `{{` means `{`. | ||
_MOLECULE = """ | ||
{{ | ||
auto molecule = new sketcherMinimizerMolecule(); | ||
std::array<std::tuple<int, float, float>, {atom_total}> atoms = {{{{ | ||
{atoms} | ||
}}}}; | ||
std::array<std::array<int, 3>, {bond_total}> bonds = {{{{ | ||
{bonds} | ||
}}}}; | ||
add_atoms(molecule, atoms); | ||
add_bonds(molecule, bonds); | ||
molecules[i] = molecule; | ||
++i; | ||
}} | ||
""" | ||
|
||
_DOC = """ | ||
/// | ||
// Find the templates for coordinate generation | ||
// | ||
// Autogenerated, do not edit. | ||
// | ||
// $SCHRODINGER/run {script_name} {template_file} | ||
// | ||
// generated using {template_file} version {git_hash}. | ||
// | ||
""" | ||
|
||
_HEADER = """ | ||
#pragma once | ||
{doc} | ||
#include <vector> | ||
class sketcherMinimizerMolecule; | ||
namespace schrodinger {{ | ||
/// | ||
// Create a new vector of sketcherMinimizerMolecule*. Caller | ||
// owns the sketcherMinimizerMolecule objects. | ||
std::vector<sketcherMinimizerMolecule*> coordgen_templates(); | ||
}} | ||
""" | ||
|
||
_IMPLEMENTATION = """ | ||
{doc} | ||
#include "{name}.h" | ||
#include <array> | ||
#include "sketcherMinimizerMolecule.h" | ||
#include "sketcherMinimizerAtom.h" | ||
#include "sketcherMinimizerBond.h" | ||
using std::array; | ||
using std::tuple; | ||
template <typename T> | ||
void add_atoms(sketcherMinimizerMolecule* molecule, const T& atoms) | ||
{{ | ||
for (const auto& a: atoms) {{ | ||
auto atom = molecule->addNewAtom(); | ||
atom->setAtomicNumber(std::get<0>(a)); | ||
atom->setCoordinates(sketcherMinimizerPointF(std::get<1>(a), std::get<2>(a))); | ||
}} | ||
}} | ||
template <typename T> | ||
void add_bonds(sketcherMinimizerMolecule* molecule, const T& bonds) | ||
{{ | ||
for (const auto& b: bonds) {{ | ||
auto* from_atom = molecule->getAtoms().at(b[0]); | ||
auto* to_atom = molecule->getAtoms().at(b[1]); | ||
auto bond = molecule->addNewBond(from_atom, to_atom); | ||
bond->setBondOrder(b[2]); | ||
}} | ||
}} | ||
namespace schrodinger {{ | ||
std::vector<sketcherMinimizerMolecule*> coordgen_templates() | ||
{{ | ||
std::vector<sketcherMinimizerMolecule*> molecules({total}); | ||
size_t i = 0; | ||
{body} | ||
return molecules; | ||
}} | ||
}} | ||
""" | ||
|
||
|
||
def get_mol_def(st): | ||
""" | ||
Use _MOLECULE to define `st` as a sketcherMinimizerMolecule | ||
""" | ||
atoms = ( | ||
f' tuple<int, float, float>({a.atomic_number}, {a.x}f, {a.y}f)' | ||
for a in st.atom) | ||
atoms = ',\n'.join(atoms) | ||
|
||
bonds = ( | ||
f' {{ {b.atom1.index - 1}, {b.atom2.index - 1}, {b.order} }}' | ||
for b in st.bond) | ||
bonds = ',\n'.join(bonds) | ||
|
||
t = _MOLECULE.format( | ||
bonds=bonds, | ||
atoms=atoms, | ||
atom_total=st.atom_total, | ||
bond_total=len(st.bond)) | ||
return t | ||
|
||
|
||
def main(args=None): | ||
parser = argparse.ArgumentParser(args) | ||
parser.add_argument('template_file') | ||
|
||
opts = parser.parse_args() | ||
|
||
git_hash = subprocess.check_output( | ||
['git', 'log', '-n', '1', '--pretty=format:%H', opts.template_file]) | ||
git_hash = git_hash.decode().strip()[:20] | ||
template_dir, template_base_name = os.path.split(opts.template_file) | ||
|
||
doc = _DOC.format( | ||
script_name=os.path.basename(__file__), | ||
template_file=template_base_name, | ||
git_hash=git_hash) | ||
|
||
header = _HEADER.format(doc=doc) | ||
|
||
total = structure.count_structures(opts.template_file) | ||
body = '' | ||
|
||
with structure.StructureReader(opts.template_file) as r: | ||
for st in r: | ||
mol_def = get_mol_def(st) | ||
body += mol_def | ||
body = textwrap.indent(body, ' ') | ||
|
||
implementation = _IMPLEMENTATION.format( | ||
doc=doc, name=NAME, body=body, total=total) | ||
|
||
header_path = os.path.join(template_dir, f'{NAME}.h') | ||
with open(header_path, 'w') as fh: | ||
fh.write(header) | ||
|
||
implementation_path = os.path.join(template_dir, f'{NAME}.cpp') | ||
with open(implementation_path, 'w') as fh: | ||
fh.write(implementation) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#pragma once | ||
|
||
/// | ||
// Shim for creating sketcherMolecules from .mae files. | ||
|
||
#include "sketcherMinimizerMolecule.h" | ||
#include "maeparser/MaeConstants.hpp" | ||
#include "maeparser/Reader.hpp" | ||
|
||
using namespace std; | ||
using namespace schrodinger; | ||
|
||
/// | ||
// A very simple utility function to parse a mae::Block into a 2D | ||
// sketcherMinimizerMolecule. Anything beyond atomic number, x and y coordinates | ||
// and bond orders will be ignored (i.e. no chiralities or stereo bonds will be | ||
// parsed). | ||
// | ||
sketcherMinimizerMolecule* mol_from_mae_block(mae::Block& block) | ||
{ | ||
auto molecule = new sketcherMinimizerMolecule(); | ||
// Atom data is in the m_atom indexed block | ||
{ | ||
const auto atom_data = block.getIndexedBlock(mae::ATOM_BLOCK); | ||
// All atoms are gauranteed to have these three field names: | ||
const auto atomic_numbers = | ||
atom_data->getIntProperty(mae::ATOM_ATOMIC_NUM); | ||
const auto xs = atom_data->getRealProperty(mae::ATOM_X_COORD); | ||
const auto ys = atom_data->getRealProperty(mae::ATOM_Y_COORD); | ||
const auto size = atomic_numbers->size(); | ||
|
||
// atomic numbers, and x, y, and z coordinates | ||
for (size_t i = 0; i < size; ++i) { | ||
auto atom = molecule->addNewAtom(); | ||
atom->setAtomicNumber(atomic_numbers->at(i)); | ||
atom->setCoordinates(sketcherMinimizerPointF( | ||
static_cast<float>(xs->at(i)), static_cast<float>(ys->at(i)))); | ||
} | ||
} | ||
|
||
// Bond data is in the m_bond indexed block | ||
{ | ||
const auto bond_data = block.getIndexedBlock(mae::BOND_BLOCK); | ||
// All bonds are gauranteed to have these three field names: | ||
auto from_atoms = bond_data->getIntProperty(mae::BOND_ATOM_1); | ||
auto to_atoms = bond_data->getIntProperty(mae::BOND_ATOM_2); | ||
auto orders = bond_data->getIntProperty(mae::BOND_ORDER); | ||
const auto size = from_atoms->size(); | ||
|
||
for (size_t i = 0; i < size; ++i) { | ||
// Maestro atoms are 1 indexed! | ||
auto* from_atom = molecule->getAtoms().at(from_atoms->at(i) - 1); | ||
auto* to_atom = molecule->getAtoms().at(to_atoms->at(i) - 1); | ||
auto bond = molecule->addNewBond(from_atom, to_atom); | ||
bond->setBondOrder(orders->at(i)); | ||
} | ||
} | ||
|
||
return molecule; | ||
} |
Oops, something went wrong.