Commit 168148a0 authored by Tauriello Gerardo's avatar Tauriello Gerardo
Browse files

Merge branch 'release-1.1'

parents db775cab da39416d
......@@ -5,6 +5,31 @@
Changelog
================================================================================
Release 1.1
--------------------------------------------------------------------------------
* Updated dependencies: need Eigen 3.3.0 and OST 1.7
* Changes in modelling pipeline: remove clashing loop candidates early, new
scores using sequence / structure profiles, new scoring weights, subrotamer
optimization to reduce ring punches, and improved handling of ligands
* Improved build-model action to generate oligomeric models, input multiple
files, and allow for residue offsets into structure files
* Improved computational runtime of relevant operations in pipeline (CCD,
scorers, backbone list operations), superpositions and loop candidate
clustering
* High-level functionality moved consistently to modelling module
* New modelling algorithms: rigid blocks to compare structures and improved
fragment sampling for de novo modelling
* New rotamer graph solvers for sidechains: AStar and Monte Carlo
* Refactored backbone scoring to simplify extensions
* Added all atom scoring with possibilities to reconstruct sidechains for
selected loops, reconstruct hydrogens and minimize energy with MM
* Refactored backbone list to speed it up
* Added runtime profiling for developers
* Several minor bug fixes, improvements, and speed-ups
Release 1.0
--------------------------------------------------------------------------------
* initial release of ProMod3 for use in productive instances of SMNG
* Initial release of ProMod3 for use in productive instances of SMNG
......@@ -8,14 +8,16 @@
# (if documentation is disabled, there is no doctest, linkcheck at all)
cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake_support)
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
project(ProMod3 CXX C)
include(PROMOD3)
# versioning info
set(PROMOD3_VERSION_MAJOR 1)
set(PROMOD3_VERSION_MINOR 0)
set(PROMOD3_VERSION_PATCH 2)
set(PROMOD3_VERSION_MINOR 1)
set(PROMOD3_VERSION_PATCH 0)
set(PROMOD3_VERSION_STRING ${PROMOD3_VERSION_MAJOR}.${PROMOD3_VERSION_MINOR})
set(PROMOD3_VERSION_STRING ${PROMOD3_VERSION_STRING}.${PROMOD3_VERSION_PATCH})
......@@ -23,6 +25,27 @@ option(DISABLE_DOCUMENTATION "Do not build documentation" OFF)
option(DISABLE_DOCTEST "Do not check examples in documentation" OFF)
option(DISABLE_LINKCHECK "Do not check links in the documentation" OFF)
# get git info: current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# get git info: latest abbreviated commit hash of the working branch
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# set PM3_RUNTIME_PROFILING_LEVEL
if(NOT PM3_RUNTIME_PROFILING_LEVEL)
set(PM3_RUNTIME_PROFILING_LEVEL 0)
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
exec_program(gcc ARGS --version OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION)
if(CMAKE_C_COMPILER_VERSION MATCHES ".*4\\.[5-9].*")
......@@ -40,6 +63,12 @@ else()
set(_OPT OFF)
endif()
if(ENABLE_SSE)
set(_ENABLE_SSE 1)
else()
set(_ENABLE_SSE 0)
endif()
setup_stage()
file(MAKE_DIRECTORY ${STAGE_DIR}
${EXECUTABLE_OUTPUT_PATH}
......@@ -55,17 +84,10 @@ if(NOT DISABLE_DOCUMENTATION)
find_package(Sphinx ${PYTHON_VERSION} REQUIRED)
set(PYTHON_DOC_URL "https://docs.python.org/${PYTHON_VERSION}")
# set this to the URL corresponding to the version of OST you are using
set(OST_DOC_URL "http://www.openstructure.org/docs/1.3")
set(OST_DOC_URL "http://www.openstructure.org/docs/dev")
endif()
find_package(OPENSTRUCTURE 1.4 REQUIRED
COMPONENTS io mol seq seq_alg mol_alg conop)
#The KIC loop closing algorithm requires a solver for a generalized eigen
#problem. Eigen3 would provide such a solver, but only allows to extract
#the resulting eigenvalues and not the eigenvectors.
#As soon as there is an Eigen3 release with the required functionality,
#The Lapack dependency can be dropped.
find_package(LAPACK)
find_package(OPENSTRUCTURE 1.7 REQUIRED
COMPONENTS io mol seq seq_alg mol_alg conop img mol_mm)
if(CMAKE_COMPILER_IS_GNUCXX)
# do not write back into cache, otherwise the compile command line gets
......@@ -80,7 +102,7 @@ endif()
# additional packages/ headers/ etc.
# Eigen3 is mandatory right now but may vanish once OST switches to the same
# version.
find_package(Eigen3 3.2.1 REQUIRED)
find_package(Eigen3 3.3.0 REQUIRED)
if(NOT EIGEN3_FOUND)
message(FATAL_ERROR "Eigen3 is essential for building ${PROJECT_NAME}.")
endif()
......@@ -88,7 +110,7 @@ endif()
# This is somewhat experimental: Checking if Boost is compiled with the same
# Python version used for Promod3. The very same macro is disabled in OST so
# it may fail at some point.
promod3_match_boost_python_version(${PYTHON_LIBRARIES})
#promod3_match_boost_python_version(${PYTHON_LIBRARIES})
# basic environment
include_directories(${Boost_INCLUDE_DIRS}
......@@ -103,9 +125,10 @@ set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
## e.g. add_subdirectory(src), subdirs have their own CMakeLists.txt
add_subdirectory(config)
add_subdirectory(core)
add_subdirectory(modelling)
add_subdirectory(sidechain)
add_subdirectory(loop)
add_subdirectory(sidechain)
add_subdirectory(scoring)
add_subdirectory(modelling)
add_subdirectory(scripts)
add_subdirectory(actions)
add_subdirectory(extras)
......
set(ACTION_RST
index.rst
index_dev.rst
)
......
.. _promod-actions:
|project| Actions
================================================================================
A pure command line interface of |project| is provided by actions.
You can execute ``pm help`` for a list of possible actions and for every action,
you can type ``pm <ACTION> -h`` to get a description on its usage.
Here we list the most prominent actions with simple examples.
.. _promod-build-model:
Building models
--------------------------------------------------------------------------------
You can run a full protein homology modelling pipeline from the command line
with
.. code-block:: console
$ pm build-model [-h] (-f <FILE> | -c <FILE> | -j <OBJECT>|<FILE>)
(-p <FILE> | -e <FILE>) [-o <FILENAME>]
Example usage:
.. code-block:: console
$ pm build-model -f aln.fasta -p tpl.pdb
This reads a target-template alignment from :file:`aln.fasta` and a matching
structure from :file:`tpl.pdb` and produces a gap-less model which is stored as
:file:`model.pdb`. The output filename can be controlled with the ``-o`` flag.
Target-template alignments can be provided in FASTA (``-f``), CLUSTAL (``-c``)
or as JSON files/objects (``-j``). Files can be plain or gzipped.
At least one alignment must be given and you cannot mix file formats.
Multiple alignment files can be given and target chains will be appended in the
given order. The chains of the target model are named with default chain names
(A, B, C, ..., see :meth:`~promod3.modelling.BuildRawModel`).
Notes on the input formats:
- Leading/trailing whitespaces of sequence names will always be deleted
- FASTA input example:
.. code-block:: none
>target
HGFHVHEFGDNTNGCMSSGPHFNPYGKEHGAPVDENRHLG
>2jlp-1.A|55
RAIHVHQFGDLSQGCESTGPHYNPLAVPH------PQHPG
Target sequence is either named "trg" or "target" or the first sequence is
used. Template sequence names can encode an identifier for the chain to attach
to it and optionally an offset (here: 55, see below for details).
Leading whitespaces of fasta headers will be deleted
- CLUSTAL input follows the same logic as FASTA input
- JSON input: filenames are not allowed to start with '{'.
JSON objects contain an entry with key 'alignmentlist'.
That in turn is an array of objects with keys 'target' and 'template'.
Those in turn are objects with keys
'name' (string id. for sequence),
'seqres' (string for aligned sequence) and optionally for templates
'offset' (number of residues to skip in structure file attached to it).
Example:
.. code-block:: json
{"alignmentlist": [ {
"target": {
"name": "mytrg",
"seqres": "HGFHVHEFGDNTNGCMSSGPHFNPYGKEHGAPVDENRHLG"
},
"template": {
"name": "2jlp-1.A",
"offset": 55,
"seqres": "RAIHVHQFGDLSQGCESTGPHYNPLAVPH------PQHPG"
}
} ] }
Structures can be provided in PDB (``-p``) or in any format readable by the
:func:`ost.io.LoadEntity` method (``-e``). In the latter case, the format is
chosen by file ending. Recognized File Extensions: ``.ent``, ``.pdb``,
``.ent.gz``, ``.pdb.gz``, ``.cif``, ``.cif.gz``. At least one structure must be
given and you cannot mix file formats. Multiple structures can be given and each
structure may have multiple chains, but care must be taken to identify which
chain to attach to which template sequence. Chains for each sequence are
identified based on the sequence name of the templates in the alignments. Valid
sequence names are:
- anything, if only one structure with one chain
- "<FILE>.<CHAIN>", where <FILE> is the base file name of an imported structure
with no extensions and <CHAIN> is the identifier of the chain in the imported
structure.
- "<FILE>" if only one chain in file
- "<CHAIN>" if only one file imported
- "<CHAINID>|<OFFSET>", where <CHAINID> identifies the chain as above and
<OFFSET> is the number of residues to skip for that chain to reach the first
residue in the aligned sequence. Leading/trailing whitespaces of <CHAINID> and
<OFFSET> are ignored.
Example: ``... -p data/2jlp.pdb.gz``, where the pdb file has chains ``A``,
``B``, ``C`` and the template sequence is named ``2jlp.A|55``.
Possible exit codes of the action:
- 0: all went well
- 1: an unhandled exception was raised
- 2: arguments cannot be parsed or required arguments are missing
- 3: failed to perform modelling (internal error)
- 4: failed to write results to file
- other non-zero: failure in argument checking
(see :class:`promod3.core.pm3argparse.PM3ArgumentParser`)
\ No newline at end of file
import os, argparse
'''
Automatically build a model from alignments and template structures.
Example usage:
pm build-model -f aln.fasta -p tpl.pdb
This reads a target-template alignment from aln.fasta and a matching
structure from tpl.pdb and produces a gap-less model which is stored
as model.pdb.
Please see the ProMod3 documentation for details on more advanced usage.
'''
import os
import ost
from ost import io, settings
from ost.bindings import dssp
from promod3 import modelling
from promod3.core import helper
### CHANGELOG - START
# 2016-03-02 - created
### CHANGELOG - END
from promod3.core import pm3argparse, helper
### EXIT STATUS - START
# 1 - template structure file does not exist
# 2 - template structure file has unsupported file extension
# 3 - alignment file does not exist
# 4 - alignment file has unsupported file extension
# 5 - failed to perform modelling (internal error)
# 6 - failed to write results to file
### EXIT STATUS - END
### SETUP - START
DESCRIPTION = '''\
Automatically build a model from an alignment and a template structure.
'''
### SETUP - END
# make sure we see output when passing '-h'
ost.PushVerbosityLevel(2)
### FUNCTIONS - START
def _ParserArgs():
p = argparse.ArgumentParser(prog="pm build-model", description=DESCRIPTION,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
p.add_argument('template_file', metavar='<TEMPLATE STRUCTURE>', type=str,
help='File providing coordinates, either PDB or mmCIF '
+'format, plain or gzipped.')
p.add_argument('alignment_file', metavar='<ALIGNMENT>', type=str,
help='File providing the target-template alignment')
p.add_argument('-o', '--model-file', metavar='<FILENAME>', type=str,
help='File to store model coordinates.', default='model.pdb')
opts = p.parse_args()
# parse command line
parser = pm3argparse.PM3ArgumentParser(__doc__, action=True)
parser.AddAlignment()
parser.AddStructure(attach_views=True)
parser.AssembleParser()
parser.add_argument('-o', '--model-file', metavar='<FILENAME>', type=str,
default='model.pdb', help='File to store model coordinates'+
' (default: %(default)s).')
# lots of checking being done here -> see PM3ArgumentParser
opts = parser.Parse()
# check arguments
helper.FileExists('Template structure', 1, opts.template_file)
helper.FileExtension('Template structure', 2, opts.template_file,
('pdb', 'cif'), gzip=True)
helper.FileExists('Alignment', 3, opts.alignment_file)
helper.FileExtension('Alignment', 4, opts.alignment_file, ('fasta', 'fas'),
gzip=False)
return opts
### FUNCTIONS - END
### MAIN - START
opts = _ParserArgs()
# report alignments and add dssp
ost.PushVerbosityLevel(3)
if len(opts.alignments) == 1:
ost.LogInfo("Build model with the following alignment:")
elif len(opts.alignments) > 1:
ost.LogInfo("Build " + str(len(opts.alignments)) + " models with the "+
"following alignments:")
dssp_usable = True
for aln in opts.alignments:
ost.LogInfo(aln.ToString(80))
if dssp_usable:
for i in range(1, aln.GetCount()):
try:
dssp.AssignDSSP(aln.GetSequence(i).GetAttachedView())
except settings.FileNotFound:
dssp_usable = False
break
if not dssp_usable:
ost.LogInfo("dssp binary is missing. You can get better modelling results "+
"if you install dssp.")
# load template structure
tpl = io.LoadEntity(opts.template_file)
# load target-template alignment
aln = io.LoadAlignment(opts.alignment_file)
# TODO: check that alignment sequences are in template
# try to add sec. structure
# model it
try:
dssp.AssignDSSP(tpl)
except settings.FileNotFound:
print "dssp binary is missing. You can get better modelling results if " +\
"you install dssp."
try:
ost.PushVerbosityLevel(3)
ost.LogInfo("Build model with following alignment:")
ost.LogInfo(aln.ToString(80))
# get raw model
aln.AttachView(1, tpl.CreateFullView())
mhandle = modelling.BuildRawModel(aln)
mhandle = modelling.BuildRawModel(opts.alignments)
# build final model
final_model = modelling.BuildFromRawModel(mhandle)
ost.PopVerbosityLevel()
except Exception as ex:
err_tpl = "An exception of type {0} occured. Arguments:\n{1!r}"
message = err_tpl.format(type(ex).__name__, ex.args)
helper.MsgErrorAndExit("Modelling failed!\n" + message, 5)
helper.MsgErrorAndExit("Failed to perform modelling! An exception of type "+
type(ex).__name__ + " occured: " + str(ex), 3)
# output
ost.PopVerbosityLevel()
io.SavePDB(final_model, opts.model_file)
if not os.path.isfile(opts.model_file):
helper.MsgErrorAndExit("Failed to write model file '%s'." % opts.model_file, 6)
### MAIN - END
# NOTE: this follows build-rawmodel
# -> interface, error checks and code may change to:
# - follow pm-help
# - use pm3argparse to get inputs
# - check that we have desired alignments in file
# - multi-template??? :o
\ No newline at end of file
helper.MsgErrorAndExit("Failed to write model file '%s'." % opts.model_file, 4)
import os, argparse
from ost import io
from promod3 import modelling
from promod3.core import helper
### CHANGELOG - START
# 2013-11-07 - created
### CHANGELOG - END
### EXIT STATUS - START
# 1 - template structure file does not exist
# 2 - template structure file has unsupported file extension
# 3 - alignment file does not exist
# 4 - alignment file has unsupported file extension
# 5 - failed to write results to file
### EXIT STATUS - END
### SETUP - START
DESCRIPTION = '''\
Create a very basic raw model from an alignment and a template structure.
'''
Create a very basic raw model from alignments and template structures.
Conserved parts are copied from the template and an incomplete pdb file is
generated.
'''
### SETUP - END
### FUNCTIONS - START
def _ParserArgs():
p = argparse.ArgumentParser(prog="pm build-rawmodel", description=DESCRIPTION,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
p.add_argument('template_file', metavar='<TEMPLATE STRUCTURE>', type=str,
help='File providing coordinates, either PDB or mmCIF '
+'format, plain or gzipped.')
p.add_argument('alignment_file', metavar='<ALIGNMENT>', type=str,
help='File providing the target-template alignment')
p.add_argument('-o', '--model-file', metavar='<FILENAME>', type=str,
help='File to store model coordinates.', default='model.pdb')
opts = p.parse_args()
# check arguments
helper.FileExists('Template structure', 1, opts.template_file)
helper.FileExtension('Template structure', 2, opts.template_file,
('pdb', 'cif'), gzip=True)
helper.FileExists('Alignment', 3, opts.alignment_file)
helper.FileExtension('Alignment', 4, opts.alignment_file, ('fasta', 'fas'),
gzip=False)
return opts
### FUNCTIONS - END
Example usage:
pm build-rawmodel -f aln.fasta -p tpl.pdb
This reads a target-template alignment from aln.fasta and a matching
structure from tpl.pdb and produces a raw model which is stored as
model.pdb.
### MAIN - START
opts = _ParserArgs()
# load template structure
tpl = io.LoadEntity(opts.template_file)
# load target-template alignment
aln = io.LoadAlignment(opts.alignment_file)
# check that alignment sequences are in template
# mark target and template sequence in alignment
# auto-mode: chains in alignment are marked as sep.A, sep.B, etc.
# how can we do multi-whatever things?
Please see the ProMod3 documentation for details on more advanced usage.
'''
aln.AttachView(1, tpl.CreateFullView())
result = modelling.BuildRawModel(aln)
io.SavePDB(result.model, opts.model_file)
import os
import ost
from ost import io
from promod3 import modelling
from promod3.core import pm3argparse, helper
# make sure we see output when passing '-h'
ost.PushVerbosityLevel(2)
# parse command line
parser = pm3argparse.PM3ArgumentParser(__doc__, action=True)
parser.AddAlignment()
parser.AddStructure(attach_views=True)
parser.AssembleParser()
parser.add_argument('-o', '--model-file', metavar='<FILENAME>', type=str,
default='model.pdb', help='File to store model coordinates'+
' (default: %(default)s).')
# lots of checking being done here -> see PM3ArgumentParser
opts = parser.Parse()
# get raw model
try:
mhandle = modelling.BuildRawModel(opts.alignments)
except Exception as ex:
helper.MsgErrorAndExit("Failed to generate raw model! An exception of "+
"type " + type(ex).__name__ + " occured: " + str(ex),
3)
# output
ost.PopVerbosityLevel()
io.SavePDB(mhandle.model, opts.model_file)
if not os.path.isfile(opts.model_file):
helper.MsgErrorAndExit("Failed to write model file '%s'." % opts.model_file, 5)
### MAIN - END
# parse args
# - we need an input alignment
# - only 2 seqs allowed, option switch to mark which one is target
# - what happens on arbitrary sequences? One has to correspond with the
# template structure
# - what happens for a alignment list?
# - option for name model file
# - default does not overwrite, but add switch to do so
# - switch to turn of reporting gaps
# - option to go calpha only
# prepare stuff
# build model
# store stuff
# return stuff?
# report gaps?
# documentation!
## Emacs magic
# Local Variables:
# mode: python
# End:
helper.MsgErrorAndExit("Failed to write model file '%s'." % opts.model_file, 4)
......@@ -23,9 +23,10 @@ class HelpActionTests(test_actions.ActionTestCase):
# test with proper inputs (and check resulting file)
pdbpath = os.path.join('data', 'gly.pdb')
faspath = os.path.join('data', 'seq_ins.fasta')
self.RunExitStatusTest(0, [pdbpath, faspath])
my_args = ['-p', pdbpath, '-f', faspath]
self.RunExitStatusTest(0, my_args)
io.LoadPDB('model.pdb')
self.RunExitStatusTest(0, ['-o mymodel.pdb', pdbpath, faspath])
self.RunExitStatusTest(0, my_args + ['-o', 'mymodel.pdb'])
io.LoadPDB('mymodel.pdb')
# clean up this test
os.remove('model.pdb')
......@@ -35,20 +36,14 @@ class HelpActionTests(test_actions.ActionTestCase):
# test error codes
pdbpath = os.path.join('data', 'gly.pdb')
faspath = os.path.join('data', 'seq.fasta')
# 1 - template structure file does not exist
self.RunExitStatusTest(1, ['dummy.pdb', faspath])
# 2 - template structure file has unsupported file extension
self.RunExitStatusTest(2, [faspath, faspath])
# 3 - alignment file does not exist
self.RunExitStatusTest(3, [pdbpath, 'dummy.fasta'])
# 4 - alignment file has unsupported file extension
self.RunExitStatusTest(4, [pdbpath, pdbpath])
# 5 - failed to perform modelling (internal error)
my_args = ['-p', pdbpath, '-f', faspath]
# 2 - wrong input (most of this tested in pm3argparse!)
self.RunExitStatusTest(2, ['-p', pdbpath])
# 3 - failed to perform modelling (internal error)
# -> we cannot really test this one...
# 6 - failed to write results to file
# 4 - failed to write results to file
failpath = os.path.join('cannotpossiblyexist', 'whatever.pdb')
self.RunExitStatusTest(6, ['-o '+failpath, pdbpath, faspath])
self.RunExitStatusTest(4, ['-o', failpath] + my_args)
if __name__ == "__main__":
from ost import testutils
......
......@@ -23,9 +23,10 @@ class HelpActionTests(test_actions.ActionTestCase):
# test with proper inputs (and check resulting file)
pdbpath = os.path.join('data', 'gly.pdb')
faspath = os.path.join('data', 'seq.fasta')
self.RunExitStatusTest(0, [pdbpath, faspath])
my_args = ['-p', pdbpath, '-f', faspath]
self.RunExitStatusTest(0, my_args)
io.LoadPDB('model.pdb')
self.RunExitStatusTest(0, ['-o mymodel.pdb', pdbpath, faspath])
self.RunExitStatusTest(0, my_args + ['-o', 'mymodel.pdb'])
io.LoadPDB('mymodel.pdb')
# clean up this test
os.remove('model.pdb')
......@@ -35,18 +36,14 @@ class HelpActionTests(test_actions.ActionTestCase):
# test error codes
pdbpath = os.path.join('data', 'gly.pdb')
faspath = os.path.join('data', 'seq.fasta')
# 1 - template structure file does not exist
self.RunExitStatusTest(1, ['dummy.pdb', faspath])
# 2 - template structure file has unsupported file extension
self.RunExitStatusTest(2, [faspath, faspath])
# 3 - alignment file does not exist
self.RunExitStatusTest(3, [pdbpath, 'dummy.fasta'])
# 4 - alignment file has unsupported file extension
self.RunExitStatusTest(4, [pdbpath, pdbpath])
# 5 - failed to write results to file
my_args = ['-p', pdbpath, '-f', faspath]
# 2 - wrong input (most of this tested in pm3argparse!)
self.RunExitStatusTest(2, ['-p', pdbpath])
# 3 - failed to generate raw model (internal error)
# -> we cannot really test this one...
# 4 - failed to write results to file
failpath = os.path.join('cannotpossiblyexist', 'whatever.pdb')
self.RunExitStatusTest(5, ['-o '+failpath, pdbpath, faspath])
self.RunExitStatusTest(4, ['-o', failpath] + my_args)
if __name__ == "__main__":
from ost import testutils
......
......@@ -16,12 +16,12 @@
# Author: Valerio Mariani, Marco Biasini, Stefan Bienert
#-------------------------------------------------------------------------------
macro(find_OPENSTRUCTURE OST_ROOT NAMES HEADER_NAMES PYMOD_NAME)
macro(find_OPENSTRUCTURE OST_ROOT HEADER_NAMES PYMOD_NAME)
if(NOT OPENSTRUCTURE_FIND_COMPONENTS)
message(FATAL_ERROR "Please specify which modules of OpenStructure you "
"would like to use after the COMPONENTS keyword.")
endif()
list(APPEND OPENSTRUCTURE_FIND_COMPONENTS base geom mol_mm)
list(APPEND OPENSTRUCTURE_FIND_COMPONENTS base geom)
list(REMOVE_DUPLICATES OPENSTRUCTURE_FIND_COMPONENTS)
foreach (LIB ${OPENSTRUCTURE_FIND_COMPONENTS})
set(FOUND_LIB FOUND_LIB-NOTFOUND)
......@@ -96,26 +96,8 @@ macro(find_OPENSTRUCTURE OST_ROOT NAMES HEADER_NAMES PYMOD_NAME)
endmacro(find_OPENSTRUCTURE)
#-------------------------------------------------------------------------------
SET(LIBNAMES
ost_base
ost_gfx