diff --git a/.gitignore b/.gitignore index 745525cae1382a56722bfdf8c69c923850d0422c..f9b94e12aec3f7a29cb4490cb370d0b3b9ef66d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ stage src/.kdev_include_paths +src/version.hh *.pyc cmake_install.cmake CMakeCache.txt diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5a252950ac25429a9b82babef51758aa04b51280..1ad3bb1fd51a795c7f307a97b6685afc45cc8596 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,11 @@ +Changes in Release 3.1.0 +-------------------------------------------------------------------------------- + + * Version string available as qmean.qmean_version or qmean.qmean_version_x + (x can be major, minor or patch) + * Several minor bug fixes, improvements + + Changes in Release 3.0.3 -------------------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index c45541e8f90ff2f25e1018ae6dede8030187b708..a236f9040ffb77d93a6b5aacf47e72163ae60c20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,17 @@ # Author: Marco Biasini #------------------------------------------------------------------------------- cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) + +set (QMEAN_VERSION_MAJOR 3) +set (QMEAN_VERSION_MINOR 1) +set (QMEAN_VERSION_PATCH 0) +set (QMEAN_VERSION_STRING ${QMEAN_VERSION_MAJOR}.${QMEAN_VERSION_MINOR}.${QMEAN_VERSION_PATCH} ) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake_support) include(QMEAN2) -project(QMEAN2) +project(QMEAN2 CXX C) if (PREFIX) set(CMAKE_INSTALL_PREFIX ${PREFIX}) @@ -48,9 +54,14 @@ endif() file(MAKE_DIRECTORY ${STAGE_DIR} ${HEADER_STAGE_PATH} ${LIB_STAGE_PATH}) +# Python needed before Boost find_package(Python 2.7.0 REQUIRED) +# Split version string +string(REPLACE "." ";" _python_version_list ${PYTHON_VERSION}) +list(GET _python_version_list 0 PYTHON_VERSION_MAJOR) +list(GET _python_version_list 1 PYTHON_VERSION_MINOR) -find_package(OPENSTRUCTURE 1.7 REQUIRED +find_package(OPENSTRUCTURE 1.10.0 REQUIRED COMPONENTS mol seq seq_alg mol_alg conop) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY) @@ -63,11 +74,30 @@ find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS unit_test_framework REQUIRED) set(BOOST_UNIT_TEST_LIBRARIES ${Boost_LIBRARIES}) set(Boost_LIBRARIES) -find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS python REQUIRED) -set(BOOST_PYTHON_LIBRARIES ${Boost_LIBRARIES}) +# starting with CMake 3.11 we could use the following instead of the foreach +# find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS +# python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} REQUIRED) +# set(BOOST_PYTHON_LIBRARIES ${Boost_LIBRARIES}) +# see https://cmake.org/cmake/help/v3.11/module/FindBoost.html +foreach(_python_lib_name python + python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} + python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} + python${PYTHON_VERSION_MAJOR}) + find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS ${_python_lib_name} QUIET) + if(Boost_FOUND) + message(STATUS "Found Boost package: " ${_python_lib_name}) + set(BOOST_PYTHON_LIBRARIES ${Boost_LIBRARIES}) + break() + else() + message(STATUS "Boost package not found: " ${_python_lib_name} + ". Trying alternative names!") + endif() +endforeach(_python_lib_name) +if(NOT BOOST_PYTHON_LIBRARIES) + message(FATAL_ERROR "Failed to find any Boost Python library!") +endif() set(Boost_LIBRARIES) -find_package(Python 2.7.0 REQUIRED) include_directories(${Boost_INCLUDE_DIRS} ${OST_INCLUDE_DIR}) diff --git a/doc/source/conf.py b/doc/source/conf.py index 86b46fe0f52476147c6e6d0fe1746963b846ced8..0b92253817e90db99628d2ae32d64a0844d5a60d 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -63,16 +63,16 @@ master_doc = 'index' # General information about the project. project = u'QMEAN' -copyright = u'2016, Gabriel Studer' +copyright = u'2016-2019, Gabriel Studer' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '2' +release = '3.1.0' # The full version, including alpha/beta/rc tags. -release = '2' +release = '3.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/example_scripts/cbeta_potential_example.py b/doc/source/example_scripts/cbeta_potential_example.py index c2998a4c34db7175f8240bf622fa7c38b6e3698f..d61b664b23187c312736ae31f31915050f147279 100644 --- a/doc/source/example_scripts/cbeta_potential_example.py +++ b/doc/source/example_scripts/cbeta_potential_example.py @@ -7,7 +7,7 @@ from qmean import CBetaStatistic, CBetaPotential from qmean import InteractionStatistic, InteractionPotential from qmean import ChemType import os -from ost import conop +from ost import conop, io import matplotlib.pyplot as plt diff --git a/doc/source/example_scripts/container_example.py b/doc/source/example_scripts/container_example.py index 6664896e14b79eaa18b529f1efa03b5b6c9f6b4a..2a9ef6e0c2d12d28a7c1cc5b299665eecec04fdf 100644 --- a/doc/source/example_scripts/container_example.py +++ b/doc/source/example_scripts/container_example.py @@ -4,6 +4,7 @@ from qmean import InteractionStatistic, InteractionPotential, \ PackingStatistic, PackingPotential, \ StatisticContainer, PotentialContainer +from ost import io import os #define some training targets used later on diff --git a/doc/source/example_scripts/disco_example.py b/doc/source/example_scripts/disco_example.py index 7eec197434697ea0b88bf891297a868e791ef3bd..9f9755a67c07eb0951b092a7814da6be7f8cf152 100644 --- a/doc/source/example_scripts/disco_example.py +++ b/doc/source/example_scripts/disco_example.py @@ -1,8 +1,10 @@ from qmean import DisCoContainer +from ost import io import numpy as np import matplotlib.pyplot as plt import os + aln_files = ["example_data/1pvv.1.A.fasta", "example_data/1v1v.1.A.fasta", "example_data/2w37.1.A.fasta", diff --git a/doc/source/example_scripts/interaction_potential_example.py b/doc/source/example_scripts/interaction_potential_example.py index a4f19d3bd663944c6d84bc704fd17878896ecd13..76df4bb3deb9f89d982d95ec7aab5de25dbfaf78 100644 --- a/doc/source/example_scripts/interaction_potential_example.py +++ b/doc/source/example_scripts/interaction_potential_example.py @@ -4,6 +4,7 @@ #load required modules from qmean import InteractionStatistic, InteractionPotential from qmean import ChemType +from ost import io import os import matplotlib.pyplot as plt diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst index 263bee33a4923a5557d2b348bee40dbd9a9361fc..5e0dc8f5c08290374ad131007bc0f47d3934fcb0 100644 --- a/doc/source/getting_started.rst +++ b/doc/source/getting_started.rst @@ -42,17 +42,17 @@ installed on your system. Build QMEAN -------------------------------------------------------------------------------- -QMEAN requires the OpenStructure framework with all its depencies to be -installed. Please follow the instructions on -`openstructure.org <http://www.openstructure.org/>`_ to compile from source. +QMEAN requires the OpenStructure framework with all its depencies to be +installed. Please follow the instructions on +`openstructure.org <http://www.openstructure.org/>`_ to compile from source. Once you successfully compiled OpenStructure, you need following python modules: * numpy * scipy * matplotlib -To compile QMEAN, change to the QMEAN directory, make a build directory and run -CMake in there by giving it the path to your openstructure installation +To compile QMEAN, change to the QMEAN directory, make a build directory and run +CMake in there by giving it the path to your OpenStructure installation (you might want to activate optimizations with -DOPTIMIZE): .. code-block:: bash @@ -85,7 +85,7 @@ Python. Following command enables QMEAN in your current shell: export PYTHONPATH=path_to_qmean_build_dir/stage/lib64/python2.7/site-packages:$PYTHONPATH -You can add this command to .bashrc, so it is set permanently. +You can add this command to ``.bashrc``, so it is set permanently. If everything is setup correctly, you can test the setup in an -interactive ost session by typing: from "qmean import *" +interactive ost session by typing: from ``qmean import *`` or, even better, run the example scripts from the documentation. diff --git a/doc/source/run_qmean_scoring.rst b/doc/source/run_qmean_scoring.rst index 0ea799c951712049e934d4a754797ccf99b9144c..48a760737ce264d6e813dc982de70744327189e6 100644 --- a/doc/source/run_qmean_scoring.rst +++ b/doc/source/run_qmean_scoring.rst @@ -104,7 +104,8 @@ Assessing the quality for soluble protein models .. method:: QMEAN6SliderPlot(out_path) Dumps the slider plot representing the QMEAN6 Z-Score and the Z-Scores of - its components. + its components. If *psipred* or *accpro* are missing, the plot makes no + sense as the Z-scores from the agreement terms and QMEAN6 are set to NaN. :param out_path: Path to dump the plot, must have image format file ending, e.g. awesome_plot.png @@ -124,7 +125,9 @@ Assessing the quality for soluble protein models .. method:: QMEAN6ReferencePlot(out_path) Dumps the reference plot with the QMEAN6 score of the *model* compared to - the QMEAN6 scores of a large set of non-redundant X-ray structures. + the QMEAN6 scores of a large set of non-redundant X-ray structures. If + *psipred* or *accpro* are missing, the plot makes no sense as the QMEAN6 + score is set to NaN. :param out_path: Path to dump the plot, must have image format file ending, e.g. awesome_plot.png @@ -179,12 +182,14 @@ Assessing the quality for soluble protein models .. attribute:: qmean6_score The QMEAN6 score of *model*, i.e. four statistical potentials and two agreement - terms linearly combined to get a global score. + terms linearly combined to get a global score. Value is set to NaN if *psipred* + or *accpro* are invalid. .. attribute:: qmean6_z_score The QMEAN6 Z-score of *model*, i.e. its QMEAN6 score compared to what one would - expect from high resolution X-ray structures + expect from high resolution X-ray structures. Value is set to NaN if *psipred* + or *accpro* are invalid. .. attribute:: qmean6_components @@ -192,7 +197,9 @@ Assessing the quality for soluble protein models and Z-score version. Keys of the dictionary: ["interaction", "cbeta", "packing", "torsion", "ss_agreement", "acc_agreement", "interaction_z_score", "cbeta_z_score", "packing_z_score", "torsion_z_score", - "ss_agreement_z_score", "acc_agreement_z_score"] + "ss_agreement_z_score", "acc_agreement_z_score"]. The values for the + agreement terms is set to NaN if the required input is missing + (*psired*, *accpro*) .. attribute:: local_scores @@ -210,9 +217,10 @@ Assessing the quality for soluble protein models The expected error for *avg_local_score*. This attribute is only available if you provided distance constraints and enabled neural networks - (*dc* and *use_nn* parameters at QMEANScorer construction). The error is the - root mean squared difference (i.e. standard deviation) between predicted - lDDT and true lDDT on a large set of models with similar size. + (*dc* and *use_nn* parameters at QMEANScorer construction). NaN is returned + otherwise. The error is the root mean squared difference + (i.e. standard deviation) between predicted lDDT and true lDDT on a large + set of models with similar size. diff --git a/pymod/__init__.py b/pymod/__init__.py index 474bda4a4c9fad16ada5702e08585aa691f445bd..c90654f832fa2a38aa79774564997b4bab0cf35c 100644 --- a/pymod/__init__.py +++ b/pymod/__init__.py @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from ost import * from _qmean import * from qmean.predicted_sequence_features import PSIPREDHandler from qmean.predicted_sequence_features import ACCPROHandler @@ -21,3 +20,4 @@ from qmean.score_calculator import LocalScorer from qmean.score_calculator import GlobalScorer from qmean.mqa_result_membrane import AssessMembraneModelQuality from qmean.mqa_result import QMEANScorer + diff --git a/pymod/export_reduced.cc b/pymod/export_reduced.cc index be681279bb17e39bd68017fefc47d13315025668..239f36ddca2264b85050fc417671a47724586bbd 100644 --- a/pymod/export_reduced.cc +++ b/pymod/export_reduced.cc @@ -29,8 +29,8 @@ Real GetCountaabin(ReducedStatisticPtr s, ost::conop::AminoAcid aa_one,ost::cono Real GetCountbin(ReducedStatisticPtr s, int a, int b, int c, int d){ return s->GetCount(a,b,c,d); } Real GetEnergy(ReducedPotentialPtr p, ost::conop::AminoAcid aa_one, ost::conop::AminoAcid aa_two, Real dist, Real alpha, Real beta, Real gamma) { return p->GetEnergy(aa_one, aa_two, dist, alpha, beta, gamma); } -Real GetEnergyRes(ReducedPotentialPtr p, ost::mol::ResidueView& res, bool normalize) { p->GetEnergy(res, normalize); } -Real GetEnergyResEnv(ReducedPotentialPtr p, ost::mol::ResidueView& res, ost::mol::EntityView& env, bool normalize) { p->GetEnergy(res, env, normalize); } +Real GetEnergyRes(ReducedPotentialPtr p, ost::mol::ResidueView& res, bool normalize) { return p->GetEnergy(res, normalize); } +Real GetEnergyResEnv(ReducedPotentialPtr p, ost::mol::ResidueView& res, ost::mol::EntityView& env, bool normalize) { return p->GetEnergy(res, env, normalize); } list WrapGetEnergies(ReducedPotentialPtr p, ost::mol::EntityView& target, ost::mol::EntityView& env, bool normalize){ std::vector<Real> energies = p->GetEnergies(target,env, normalize); diff --git a/pymod/mqa_membrane.py b/pymod/mqa_membrane.py index cbd6f5b244e3410e19919f1b694e75fa5df791ff..7e96de0373aa14d624c79ade724f345ca63e4b20 100644 --- a/pymod/mqa_membrane.py +++ b/pymod/mqa_membrane.py @@ -15,7 +15,7 @@ from qmean import * from qmean import conf -from ost import mol +from ost import mol, geom import pickle from predicted_sequence_features import AlignChainToSEQRES diff --git a/pymod/mqa_result.py b/pymod/mqa_result.py index 6733cd264412f284b9a69aaf3d25ccb431fd3022..49aeabdd078b34e42c182b2ca6781e7c21624816 100644 --- a/pymod/mqa_result.py +++ b/pymod/mqa_result.py @@ -168,12 +168,13 @@ class QMEANScorer(object): def qmean6_score(self): if self._qmean6_score == None: if self._psipred == None or self._accpro == None: - raise RuntimeError("Require PSIPRED and ACCPRO information for QMEAN6") - data = self.global_mqa.GetAVGData(['interaction','cbeta', - 'packing','torsion', - 'ss_agreement', 'acc_agreement']) - s = self.linear_global_scorer.GetGlobalScore('soluble', data) - self._qmean6_score = min(max(s, 0.0), 1.0) + self._qmean6_score = float("NaN") + else: + data = self.global_mqa.GetAVGData(['interaction','cbeta', + 'packing','torsion', + 'ss_agreement', 'acc_agreement']) + s = self.linear_global_scorer.GetGlobalScore('soluble', data) + self._qmean6_score = min(max(s, 0.0), 1.0) return self._qmean6_score diff --git a/pymod/mqa_result_membrane.py b/pymod/mqa_result_membrane.py index aece5fc8082b39a5192c63053cb9a6be882d25da..1dba872437fdee14052c942bc6e86507f6dec2a3 100644 --- a/pymod/mqa_result_membrane.py +++ b/pymod/mqa_result_membrane.py @@ -18,6 +18,7 @@ from qmean import mqa_membrane from qmean import score_calculator from qmean import reference_set from qmean import conf +from ost import conop from ost.table import * import os import matplotlib diff --git a/pymod/wrap_qmean.cc b/pymod/wrap_qmean.cc index 34180455c9faef384b577e3cecee103b0bffc752..9725557906cfea795decc17e0d2b31e6b19c7cc2 100644 --- a/pymod/wrap_qmean.cc +++ b/pymod/wrap_qmean.cc @@ -15,6 +15,7 @@ #include <boost/python.hpp> #include <ost/mol/entity_handle.hh> +#include <qmean/version.hh> void export_Torsion(); void export_Interaction(); @@ -33,6 +34,13 @@ using namespace boost::python; BOOST_PYTHON_MODULE(_qmean) { + // attach version information to current modules scope + scope().attr("qmean_version") = QMEAN_VERSION_STRING; + scope().attr("qmean_version_major") = QMEAN_VERSION_MAJOR; + scope().attr("qmean_version_minor") = QMEAN_VERSION_MINOR; + scope().attr("qmean_version_patch") = QMEAN_VERSION_PATCH; + + // export qmean functionality export_Base(); export_Torsion(); export_Interaction(); diff --git a/scripts/bump-version.py b/scripts/bump-version.py new file mode 100644 index 0000000000000000000000000000000000000000..7ef8060ac57afeed3dbd7f719da4a118cb30004c --- /dev/null +++ b/scripts/bump-version.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +import sys + +if len(sys.argv) < 3: + print "USAGE: python scripts/bump-version.py QMEAN_VERSION OST_VERSION" + print "-> *_VERSION format is MAJOR.MINOR.PATCH (e.g. 1.9.1)" + print "-> assumption is that git tags will exist for those *_VERSION" + sys.exit(1) + +# split up version number +version_string = sys.argv[1] +version = version_string.split('.') +major, minor, patch = (int(version[0]), int(version[1]), int(version[2])) +ost_version_string = sys.argv[2] + +# fix CMakeLists +lines = open("CMakeLists.txt").readlines() +for i, line in enumerate(lines): + if line.startswith("set (QMEAN_VERSION_MAJOR"): + lines[i] = "set (QMEAN_VERSION_MAJOR %d)\n" % major + elif line.startswith("set (QMEAN_VERSION_MINOR"): + lines[i] = "set (QMEAN_VERSION_MINOR %d)\n" % minor + elif line.startswith("set (QMEAN_VERSION_PATCH"): + lines[i] = "set (QMEAN_VERSION_PATCH %d)\n" % patch + elif line.startswith("find_package(OPENSTRUCTURE "): + lines[i] = "find_package(OPENSTRUCTURE %s REQUIRED\n" % ost_version_string +open("CMakeLists.txt", "w").writelines(lines) + +# fix CHANGELOG +lines = open("CHANGELOG.txt").readlines() +for i, line in enumerate(lines): + if line.startswith("Changes in Release") and "X" in line.upper(): + lines[i] = "Changes in Release %s\n" % version_string +open("CHANGELOG.txt", "w").writelines(lines) + +# fix doc config +lines = open("doc/source/conf.py").readlines() +for i, line in enumerate(lines): + if line.startswith("version = "): + lines[i] = "version = '%d.%d'\n" % (major, minor) + elif line.startswith("release = "): + lines[i] = "release = '%s'\n" % version_string +open("doc/source/conf.py", "w").writelines(lines) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 20997baaf7ec3fcbc9d622f6a97ff7aca7daa0c8..ddade4bea0418da8b83a7295d6efad4f072f9a40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,7 @@ hbond_potential.hh ss_agreement.hh spherical_smoother.hh vec_list_magic.hh +version.hh disco.hh clash_score.hh impl/reduced_impl.hh @@ -66,6 +67,9 @@ impl/cb_packing_impl.cc impl/hbond_impl.cc ) +set(config_hh_generator "CMake") +set(VERSION_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/version.hh") +configure_file(version.hh.in ${VERSION_HH_FILE}) module(NAME qmean SOURCES ${QMEAN_SOURCES} HEADERS ${QMEAN_HEADERS} PREFIX "" HEADER_OUTPUT_DIR qmean diff --git a/src/disco.cc b/src/disco.cc index deb0c0da5136fdcac680c5a977f4666db5272fe4..c7804a57aef019cf7eb357fffd34605e378cab4f 100644 --- a/src/disco.cc +++ b/src/disco.cc @@ -705,13 +705,7 @@ DisCoContainerPtr DisCoContainer::Load(const String& filename) { std::ifstream in_stream(filename.c_str(), std::ios::binary); if(!in_stream){ throw std::runtime_error("Could not open file " + filename); - } - - // number of bytes of the whole file - // this will be relevant to determine how many constraints there are to load - in_stream.seekg (0, in_stream.end); - long int total_num_bytes = in_stream.tellg(); - in_stream.seekg (0, in_stream.beg); + } // the variables to load char cvalue; @@ -762,11 +756,14 @@ DisCoContainerPtr DisCoContainer::Load(const String& filename) { uint16_t j; std::vector<uint8_t> loaded_vec(loaded_container->num_bins_, 0); - // always check whether there are enough bytes to read for one more constraint - while(in_stream.good() && - in_stream.tellg() + constraint_num_bytes <= total_num_bytes) { + // abort check with first read + while (true) { in_stream.read(reinterpret_cast<char*>(&i), sizeof(uint16_t)); + + // abort if no more data + if (!in_stream) break; + in_stream.read(reinterpret_cast<char*>(&j), sizeof(uint16_t)); ConstraintInfo* constraint_info = new ConstraintInfo; diff --git a/src/impl/cbeta_impl.cc b/src/impl/cbeta_impl.cc index b2046704e0d62d386de8d67f3ad155f2087239bc..914f8cf432343fcdb5caddcf246a1d9e351ae3d2 100644 --- a/src/impl/cbeta_impl.cc +++ b/src/impl/cbeta_impl.cc @@ -112,6 +112,9 @@ bool CBetaPotentialImpl::VisitResidue(const ost::mol::ResidueHandle& res){ } this->OnInteraction(aa, it->aa, dist); } + + // no need to continue to atoms + return false; } }} diff --git a/src/impl/interaction_impl.cc b/src/impl/interaction_impl.cc index ce2954178972937c82368b61d5b789135da3712a..dbce04f9bc5040b6c1928a5ce9ef772a762b1988 100644 --- a/src/impl/interaction_impl.cc +++ b/src/impl/interaction_impl.cc @@ -79,6 +79,8 @@ bool InteractionPotentialImpl::VisitAtom(const ost::mol::AtomHandle& at){ this->OnInteraction(type_a, type_b, dist); } + + return true; } }} //namespaces diff --git a/src/version.hh.in b/src/version.hh.in new file mode 100644 index 0000000000000000000000000000000000000000..c7ad4a71dbddbcf14571b6033e0a9e6c8a154db7 --- /dev/null +++ b/src/version.hh.in @@ -0,0 +1,25 @@ +// Copyright (c) 2013-2018, SIB - Swiss Institute of Bioinformatics and +// Biozentrum - University of Basel +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef QMEAN_VERSION_HH_ +#define QMEAN_VERSION_HH_ + +#define QMEAN_VERSION_MAJOR @QMEAN_VERSION_MAJOR@ +#define QMEAN_VERSION_MINOR @QMEAN_VERSION_MINOR@ +#define QMEAN_VERSION_PATCH @QMEAN_VERSION_PATCH@ +#define QMEAN_VERSION_STRING "@QMEAN_VERSION_STRING@" + +#endif /* QMEAN_VERSION_HH_ */ +