Commit 7a1d3dbd by Maarten L. Hekkelman

Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop

parents 4bf10df0 d84faad1
......@@ -25,7 +25,7 @@
cmake_minimum_required(VERSION 3.16)
# set the project name
project(cifpp VERSION 5.0.6 LANGUAGES CXX)
project(cifpp VERSION 5.0.8 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
......@@ -89,6 +89,7 @@ if(BUILD_FOR_CCP4)
list(APPEND CMAKE_MODULE_PATH "$ENV{CCP4}")
list(APPEND CMAKE_PREFIX_PATH "$ENV{CCP4}")
set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}")
set(CMAKE_INSTALL_FULL_DATADIR "${CMAKE_INSTALL_PREFIX}/share/libcifpp")
if(WIN32)
set(BUILD_SHARED_LIBS ON)
......@@ -173,6 +174,12 @@ list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
include(FindAtomic)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
if(MSVC)
# this dependency can go once MSVC supports std::experimental::is_detected
find_package(zeep 5.1.8 REQUIRED)
list(APPEND CIFPP_REQUIRED_LIBRARIES zeep::zeep)
endif()
# Create a revision file, containing the current git version info
include(VersionString)
write_version_header(${PROJECT_SOURCE_DIR}/src/ "LibCIFPP")
......
Version 5.0.8
- implemented find_first, find_min, find_max and count in category
- find1 now throws an exception if condition does not not exactly match one row
- Change in writing out PDB files, now looking up the original auth_seq_num
via the pdbx_xxx_scheme categories based on the atom_site.auth_seq_num ->
pdbx_xxx_scheme.pdb_seq_num relationship.
Version 5.0.7.1
- Use the implementation from zeep for std::experimental::is_detected
Version 5.0.7
- Reintroduce exports file. For DLL's
Version 5.0.6
- Fix file::contains, using iequals
- Fix is_cis
......
......@@ -5,6 +5,10 @@ find_dependency(Threads)
find_dependency(ZLIB REQUIRED)
if(MSVC)
find_dependency(zeep REQUIRED)
endif()
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_CIFPP_DATA_DIR@")
......
......@@ -49,7 +49,18 @@ class duplicate_key_error : public std::runtime_error
{
public:
duplicate_key_error(const std::string &msg)
: std::runtime_error(msg) {}
: std::runtime_error(msg)
{
}
};
class multiple_results_error : public std::runtime_error
{
public:
multiple_results_error()
: std::runtime_error("query should have returned exactly one row")
{
}
};
// --------------------------------------------------------------------
......@@ -109,52 +120,52 @@ class category
reference front()
{
return {*this, *m_head};
return { *this, *m_head };
}
const_reference front() const
{
return {const_cast<category &>(*this), const_cast<row &>(*m_head)};
return { const_cast<category &>(*this), const_cast<row &>(*m_head) };
}
reference back()
{
return {*this, *m_tail};
return { *this, *m_tail };
}
const_reference back() const
{
return {const_cast<category &>(*this), const_cast<row &>(*m_tail)};
return { const_cast<category &>(*this), const_cast<row &>(*m_tail) };
}
iterator begin()
{
return {*this, m_head};
return { *this, m_head };
}
iterator end()
{
return {*this, nullptr};
return { *this, nullptr };
}
const_iterator begin() const
{
return {*this, m_head};
return { *this, m_head };
}
const_iterator end() const
{
return {*this, nullptr};
return { *this, nullptr };
}
const_iterator cbegin() const
{
return {*this, m_head};
return { *this, m_head };
}
const_iterator cend() const
{
return {*this, nullptr};
return { *this, nullptr };
}
size_t size() const
......@@ -189,64 +200,64 @@ class category
iterator_proxy<const category, Ts...> rows(Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<const category, Ts...>(*this, begin(), {names...});
return iterator_proxy<const category, Ts...>(*this, begin(), { names... });
}
template <typename... Ts, typename... Ns>
iterator_proxy<category, Ts...> rows(Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<category, Ts...>(*this, begin(), {names...});
return iterator_proxy<category, Ts...>(*this, begin(), { names... });
}
// --------------------------------------------------------------------
conditional_iterator_proxy<category> find(condition &&cond)
{
return find(begin(), std::forward<condition>(cond));
return find(begin(), std::move(cond));
}
conditional_iterator_proxy<category> find(iterator pos, condition &&cond)
{
return {*this, pos, std::forward<condition>(cond)};
return { *this, pos, std::move(cond) };
}
conditional_iterator_proxy<const category> find(condition &&cond) const
{
return find(cbegin(), std::forward<condition>(cond));
return find(cbegin(), std::move(cond));
}
conditional_iterator_proxy<const category> find(const_iterator pos, condition &&cond) const
{
return conditional_iterator_proxy<const category>{*this, pos, std::forward<condition>(cond)};
return conditional_iterator_proxy<const category>{ *this, pos, std::move(cond) };
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<category, Ts...> find(condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Ns>(names)...);
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const category, Ts...> find(condition &&cond, Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Ns>(names)...);
return find<Ts...>(cbegin(), std::move(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<category, Ts...> find(const_iterator pos, condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return {*this, pos, std::forward<condition>(cond), std::forward<Ns>(names)...};
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const category, Ts...> find(const_iterator pos, condition &&cond, Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return {*this, pos, std::forward<condition>(cond), std::forward<Ns>(names)...};
return { *this, pos, std::move(cond), std::forward<Ns>(names)... };
}
// --------------------------------------------------------------------
......@@ -254,40 +265,49 @@ class category
row_handle find1(condition &&cond)
{
return find1(begin(), std::forward<condition>(cond));
return find1(begin(), std::move(cond));
}
row_handle find1(iterator pos, condition &&cond)
{
auto h = find(pos, std::forward<condition>(cond));
auto h = find(pos, std::move(cond));
if (h.size() != 1)
throw multiple_results_error();
return h.size() != 1 ? row_handle{} : *h.begin();
return *h.begin();
}
const row_handle find1(condition &&cond) const
{
return find1(cbegin(), std::forward<condition>(cond));
return find1(cbegin(), std::move(cond));
}
const row_handle find1(const_iterator pos, condition &&cond) const
{
auto h = find(pos, std::forward<condition>(cond));
auto h = find(pos, std::move(cond));
return h.size() != 1 ? row_handle{} : *h.begin();
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
template <typename T>
T find1(condition &&cond, const char *column) const
{
return find1<T>(cbegin(), std::forward<condition>(cond), column);
return find1<T>(cbegin(), std::move(cond), column);
}
template <typename T>
T find1(const_iterator pos, condition &&cond, const char *column) const
{
auto h = find<T>(pos, std::forward<condition>(cond), column);
auto h = find<T>(pos, std::move(cond), column);
if (h.size() != 1)
throw multiple_results_error();
return h.size() == 1 ? *h.begin() : T{};
return *h.begin();
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
......@@ -295,16 +315,119 @@ class category
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
return find1<Ts...>(cbegin(), std::forward<condition>(cond), std::forward<Cs>(columns)...);
return find1<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(const_iterator pos, condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::forward<condition>(cond), std::forward<Cs>(columns)...);
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
if (h.size() != 1)
throw multiple_results_error();
return *h.begin();
}
// --------------------------------------------------------------------
// if you want only a first hit
row_handle find_first(condition &&cond)
{
return find_first(begin(), std::move(cond));
}
row_handle find_first(iterator pos, condition &&cond)
{
auto h = find(pos, std::move(cond));
return h.empty() ? row_handle{} : *h.begin();
}
const row_handle find_first(condition &&cond) const
{
return find_first(cbegin(), std::move(cond));
}
const row_handle find_first(const_iterator pos, condition &&cond) const
{
auto h = find(pos, std::move(cond));
return h.empty() ? row_handle{} : *h.begin();
}
template <typename T>
T find_first(condition &&cond, const char *column) const
{
return find_first<T>(cbegin(), std::move(cond), column);
}
template <typename T>
T find_first(const_iterator pos, condition &&cond, const char *column) const
{
auto h = find<T>(pos, std::move(cond), column);
return h.empty() ? T{} : *h.begin();
}
return h.size() == 1 ? *h.begin() : std::tuple<Ts...>{};
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find_first(condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
return find_first<Ts...>(cbegin(), std::move(cond), std::forward<Cs>(columns)...);
}
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find_first(const_iterator pos, condition &&cond, Cs... columns) const
{
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::move(cond), std::forward<Cs>(columns)...);
return h.empty() ? std::tuple<Ts...>{} : *h.begin();
}
// --------------------------------------------------------------------
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column, condition &&cond) const
{
T result = std::numeric_limits<T>::min();
for (auto v : find<T>(std::move(cond), column))
{
if (result < v)
result = v;
}
return result;
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column) const
{
return find_max<T>(column, all());
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column, condition &&cond) const
{
T result = std::numeric_limits<T>::max();
for (auto v : find<T>(std::move(cond), column))
{
if (result > v)
result = v;
}
return result;
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column) const
{
return find_min<T>(column, all());
}
bool exists(condition &&cond) const
......@@ -335,6 +458,31 @@ class category
return result;
}
size_t count(condition &&cond) const
{
size_t result = 0;
if (cond)
{
cond.prepare(*this);
auto sh = cond.single();
if (sh.has_value() and *sh)
result = 1;
else
{
for (auto r : *this)
{
if (cond(r))
++result;
}
}
}
return result;
}
// --------------------------------------------------------------------
bool has_children(row_handle r) const;
......@@ -486,7 +634,7 @@ class category
// --------------------------------------------------------------------
void sort(std::function<int(row_handle,row_handle)> f);
void sort(std::function<int(row_handle, row_handle)> f);
void reorder_by_index();
// --------------------------------------------------------------------
......@@ -583,7 +731,7 @@ class category
void swap_item(uint16_t column_ix, row_handle &a, row_handle &b);
// --------------------------------------------------------------------
std::string m_name;
std::vector<item_column> m_columns;
const validator *m_validator = nullptr;
......
......@@ -182,6 +182,33 @@ namespace detail
uint16_t m_item_ix = 0;
};
struct key_is_not_empty_condition_impl : public condition_impl
{
key_is_not_empty_condition_impl(const std::string &item_tag)
: m_item_tag(item_tag)
{
}
condition_impl *prepare(const category &c) override
{
m_item_ix = get_column_ix(c, m_item_tag);
return this;
}
bool test(row_handle r) const override
{
return not r[m_item_ix].empty();
}
void str(std::ostream &os) const override
{
os << m_item_tag << " IS NOT NULL";
}
std::string m_item_tag;
uint16_t m_item_ix = 0;
};
struct key_equals_condition_impl : public condition_impl
{
key_equals_condition_impl(item &&i)
......@@ -824,6 +851,11 @@ inline condition operator==(const key &key, const empty_type &)
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
}
inline condition operator!=(const key &key, const empty_type &)
{
return condition(new detail::key_is_not_empty_condition_impl(key.m_item_tag));
}
inline condition operator not(condition &&rhs)
{
return condition(new detail::not_condition_impl(std::move(rhs)));
......
......@@ -39,66 +39,8 @@
#if __has_include(<experimental/type_traits>)
#include <experimental/type_traits>
#else
#include <type_traits>
#endif
#if (not defined(__cpp_lib_experimental_detect) or (__cpp_lib_experimental_detect < 201505)) and (not defined(_LIBCPP_VERSION) or _LIBCPP_VERSION < 5000)
// This code is copied from:
// https://ld2015.scusa.lsu.edu/cppreference/en/cpp/experimental/is_detected.html
namespace std
{
template< class... >
using void_t = void;
namespace experimental
{
namespace detail
{
template <class Default, class AlwaysVoid,
template<class...> class Op, class... Args>
struct detector
{
using value_t = false_type;
using type = Default;
};
template <class Default, template<class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
// Note that std::void_t is a c++17 feature
using value_t = true_type;
using type = Op<Args...>;
};
} // namespace detail
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template <template<class...> class Op, class... Args>
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template <template<class...> class Op, class... Args>
constexpr inline bool is_detected_v = is_detected<Op,Args...>::value;
template <template<class...> class Op, class... Args>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
template <class Default, template<class...> class Op, class... Args>
using detected_or = detail::detector<Default, void, Op, Args...>;
template <class Expected, template <class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <class Expected, template<class...> class Op, class... Args>
constexpr inline bool is_detected_exact_v = is_detected_exact<Expected, Op, Args...>::value;
}
}
// sub optimal, but replicating the same code is worse
#include <zeep/type-traits.hpp>
#endif
namespace cif
......
......@@ -1028,6 +1028,9 @@ atom_type_traits::atom_type_traits(const std::string& symbol)
break;
}
}
if (symbol == "X")
m_info = &data::kKnownAtoms[0];
if (m_info == nullptr)
throw std::invalid_argument("Not a known element: " + symbol);
......
......@@ -1780,7 +1780,7 @@ std::string structure::insert_compound(const std::string &compoundID, bool is_en
{
auto &pdbxEntityNonpoly = m_db["pdbx_entity_nonpoly"];
entity_id = pdbxEntityNonpoly.find1<std::string>("comp_id"_key == compoundID, "entity_id");
entity_id = pdbxEntityNonpoly.find_first<std::string>("comp_id"_key == compoundID, "entity_id");
if (entity_id.empty())
{
......@@ -1954,7 +1954,7 @@ void structure::change_residue(residue &res, const std::string &newCompound,
// create a copy of the entity first
auto &entity = m_db["entity"];
entityID = entity.find1<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), "id");
entityID = entity.find_first<std::string>("type"_key == "non-polymer" and "pdbx_description"_key == compound->name(), "id");
if (entityID.empty())
{
......@@ -2573,7 +2573,7 @@ std::string structure::create_entity_for_branch(branch &branch)
auto &entity = m_db["entity"];
std::string entityID = entity.find1<std::string>("type"_key == "branched" and "pdbx_description"_key == entityName, "id");
std::string entityID = entity.find_first<std::string>("type"_key == "branched" and "pdbx_description"_key == entityName, "id");
if (entityID.empty())
{
......
......@@ -122,9 +122,9 @@ std::string cifSoftware(const datablock &db, SoftwareType sw)
{
switch (sw)
{
case eRefinement: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "structure_refinement"); break;
case eDataScaling: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ds"); break;
case eDataReduction: result = db["computing"].find1<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ii"); break;
case eRefinement: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "structure_refinement"); break;
case eDataScaling: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ds"); break;
case eDataReduction: result = db["computing"].find_first<std::string>(key("entry_id") == db.name(), "pdbx_data_reduction_ii"); break;
default: break;
}
......@@ -136,11 +136,11 @@ std::string cifSoftware(const datablock &db, SoftwareType sw)
switch (sw)
{
case eRefinement: r = software.find1(key("classification") == "refinement"); break;
case eDataScaling: r = software.find1(key("classification") == "data scaling"); break;
case eDataExtraction: r = software.find1(key("classification") == "data extraction"); break;
case eDataReduction: r = software.find1(key("classification") == "data reduction"); break;
case ePhasing: r = software.find1(key("classification") == "phasing"); break;
case eRefinement: r = software.find_first(key("classification") == "refinement"); break;
case eDataScaling: r = software.find_first(key("classification") == "data scaling"); break;
case eDataExtraction: r = software.find_first(key("classification") == "data extraction"); break;
case eDataReduction: r = software.find_first(key("classification") == "data reduction"); break;
case ePhasing: r = software.find_first(key("classification") == "phasing"); break;
}
if (not r.empty())
......@@ -958,7 +958,7 @@ void WriteRemark3BusterTNT(std::ostream &pdbFile, const datablock &db)
for (auto t : tls)
{
std::string id = t["id"].as<std::string>();
auto g = db["pdbx_refine_tls_group"].find1(key("refine_tls_id") == id);
auto g = db["pdbx_refine_tls_group"].find_first(key("refine_tls_id") == id);
pdbFile << RM3("") << std::endl
<< RM3(" TLS GROUP : ") << id << std::endl
......@@ -1656,7 +1656,7 @@ void WriteRemark3Phenix(std::ostream &pdbFile, const datablock &db)
{
std::string id = t["id"].as<std::string>();
auto pdbx_refine_tls_group = db["pdbx_refine_tls_group"].find1(key("refine_tls_id") == id);
auto pdbx_refine_tls_group = db["pdbx_refine_tls_group"].find_first(key("refine_tls_id") == id);
pdbFile << RM3(" TLS GROUP : ") << id << std::endl
<< RM3(" SELECTION: ") << Fs(pdbx_refine_tls_group, "selection_details") << std::endl
......@@ -2188,20 +2188,20 @@ void WriteRemark200(std::ostream &pdbFile, const datablock &db)
std::string diffrn_id = diffrn["id"].as<std::string>();
std::string crystal_id = diffrn["crystal_id"].as<std::string>();
auto diffrn_radiation = db["diffrn_radiation"].find1(key("diffrn_id") == diffrn_id);
auto diffrn_radiation_wavelength = db["diffrn_radiation_wavelength"].find1(key("id") == diffrn_radiation["wavelength_id"].as<std::string>());
auto diffrn_source = db["diffrn_source"].find1(key("diffrn_id") == diffrn_id);
auto diffrn_detector = db["diffrn_detector"].find1(key("diffrn_id") == diffrn_id);
auto exptl = db["exptl"].find1(key("entry_id") == db.name());
auto exptl_crystal = db["exptl_crystal"].find1(key("id") == crystal_id);
auto exptl_crystal_grow = db["exptl_crystal_grow"].find1(key("crystal_id") == crystal_id);
auto computing = db["computing"].find1(key("entry_id") == db.name());
auto reflns = db["reflns"].find1(key("entry_id") == db.name());
auto diffrn_radiation = db["diffrn_radiation"].find_first(key("diffrn_id") == diffrn_id);
auto diffrn_radiation_wavelength = db["diffrn_radiation_wavelength"].find_first(key("id") == diffrn_radiation["wavelength_id"].as<std::string>());
auto diffrn_source = db["diffrn_source"].find_first(key("diffrn_id") == diffrn_id);
auto diffrn_detector = db["diffrn_detector"].find_first(key("diffrn_id") == diffrn_id);
auto exptl = db["exptl"].find_first(key("entry_id") == db.name());
auto exptl_crystal = db["exptl_crystal"].find_first(key("id") == crystal_id);
auto exptl_crystal_grow = db["exptl_crystal_grow"].find_first(key("crystal_id") == crystal_id);
auto computing = db["computing"].find_first(key("entry_id") == db.name());
auto reflns = db["reflns"].find_first(key("entry_id") == db.name());
std::string pdbx_diffrn_id = reflns["pdbx_diffrn_id"].as<std::string>();
auto reflns_shell = db["reflns_shell"].find1(key("pdbx_diffrn_id") == pdbx_diffrn_id);
auto refine = db["refine"].find1(key("pdbx_diffrn_id") == pdbx_diffrn_id);
auto reflns_shell = db["reflns_shell"].find_first(key("pdbx_diffrn_id") == pdbx_diffrn_id);
auto refine = db["refine"].find_first(key("pdbx_diffrn_id") == pdbx_diffrn_id);
std::string date =
diffrn_detector.empty() ? "NULL" : cif2pdbDate(diffrn_detector["pdbx_collection_date"].as<std::string>());
......@@ -2326,7 +2326,7 @@ void WriteRemark280(std::ostream &pdbFile, const datablock &db)
for (auto exptl_crystal : db["exptl_crystal"])
{
std::string crystal_id = exptl_crystal["id"].as<std::string>();
auto exptl_crystal_grow = db["exptl_crystal_grow"].find1(key("crystal_id") == crystal_id);
auto exptl_crystal_grow = db["exptl_crystal_grow"].find_first(key("crystal_id") == crystal_id);
pdbFile
<< RM("") << std::endl
......@@ -2458,7 +2458,7 @@ void WriteRemark350(std::ostream &pdbFile, const datablock &db)
}
}
auto gen = db["pdbx_struct_assembly_gen"].find1(key("assembly_id") == id);
auto gen = db["pdbx_struct_assembly_gen"].find_first(key("assembly_id") == id);
if (gen)
{
......@@ -2472,7 +2472,7 @@ void WriteRemark350(std::ostream &pdbFile, const datablock &db)
for (auto oper_id : split<std::string>(oper_id_list, ",", true))
{
auto r = db["pdbx_struct_oper_list"].find1(key("id") == oper_id);
auto r = db["pdbx_struct_oper_list"].find_first(key("id") == oper_id);
pdbFile << RM(" BIOMT1 ", -3) << Fs(r, "id")
<< SEP(" ", -9, 6) << Ff(r, "matrix[1][1]")
......@@ -2952,7 +2952,7 @@ int WriteHeterogen(std::ostream &pdbFile, const datablock &db)
if (id == water_comp_id)
continue;
std::string syn = db["chem_comp"].find1<std::string>(key("id") == id, "pdbx_synonyms");
std::string syn = db["chem_comp"].find_first<std::string>(key("id") == id, "pdbx_synonyms");
if (syn.empty())
continue;
......@@ -3105,7 +3105,7 @@ std::tuple<int, int> WriteSecondaryStructure(std::ostream &pdbFile, const databl
std::string initResName, initChainID, initICode, endResName, endChainID, endICode;
int initSeqNum, endSeqNum;
auto r1 = db["struct_sheet_range"].find1(key("sheet_id") == sheetID and key("id") == rangeID1);
auto r1 = db["struct_sheet_range"].find_first(key("sheet_id") == sheetID and key("id") == rangeID1);
cif::tie(initResName, initICode, endResName, endICode,
initResName, initChainID, initSeqNum, endResName, endChainID, endSeqNum) = r1.get("beg_label_comp_id", "pdbx_beg_PDB_ins_code", "end_label_comp_id",
......@@ -3120,7 +3120,7 @@ std::tuple<int, int> WriteSecondaryStructure(std::ostream &pdbFile, const databl
std::string initResName, initChainID, initICode, endResName, endChainID, endICode, curAtom, curResName, curChainID, curICode, prevAtom, prevResName, prevChainID, prevICode;
int initSeqNum, endSeqNum, curResSeq, prevResSeq;
auto r2 = db["struct_sheet_range"].find1(key("sheet_id") == sheetID and key("id") == rangeID2);
auto r2 = db["struct_sheet_range"].find_first(key("sheet_id") == sheetID and key("id") == rangeID2);
cif::tie(initResName, initICode, endResName, endICode,
initResName, initChainID, initSeqNum, endResName, endChainID, endSeqNum) = r2.get("beg_label_comp_id", "pdbx_beg_PDB_ins_code", "end_label_comp_id",
......@@ -3289,10 +3289,10 @@ int WriteMiscellaneousFeatures(std::ostream &pdbFile, const datablock &db)
void WriteCrystallographic(std::ostream &pdbFile, const datablock &db)
{
auto r = db["symmetry"].find1(key("entry_id") == db.name());
auto r = db["symmetry"].find_first(key("entry_id") == db.name());
std::string symmetry = r["space_group_name_H-M"].as<std::string>();
r = db["cell"].find1(key("entry_id") == db.name());
r = db["cell"].find_first(key("entry_id") == db.name());
pdbFile << cif::format("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11.11s%4d", r["length_a"].as<double>(), r["length_b"].as<double>(), r["length_c"].as<double>(), r["angle_alpha"].as<double>(), r["angle_beta"].as<double>(), r["angle_gamma"].as<double>(), symmetry, r["Z_PDB"].as<int>()) << std::endl;
}
......@@ -3339,10 +3339,16 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
const std::map<std::string, std::tuple<std::string, int, std::string>> &last_resseq_for_chain_map,
std::set<std::string> &terminatedChains, int model_nr)
{
using namespace cif::literals;
int numCoord = 0, numTer = 0;
auto &atom_site = db["atom_site"];
auto &atom_site_anisotrop = db["atom_site_anisotrop"];
auto &entity = db["entity"];
auto &pdbx_poly_seq_scheme = db["pdbx_poly_seq_scheme"];
auto &pdbx_nonpoly_scheme = db["pdbx_nonpoly_scheme"];
auto &pdbx_branch_scheme = db["pdbx_branch_scheme"];
int serial = 1;
auto ri = atom_site.begin();
......@@ -3405,6 +3411,16 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
r.get("id", "group_PDB", "label_atom_id", "label_alt_id", "auth_comp_id", "auth_asym_id", "auth_seq_id",
"pdbx_PDB_ins_code", "Cartn_x", "Cartn_y", "Cartn_z", "occupancy", "B_iso_or_equiv", "type_symbol", "pdbx_formal_charge");
int entity_id = r.get<int>("label_entity_id");
auto type = entity.find1<std::string>("id"_key == entity_id, "type");
if (type == "branched") // find the real auth_seq_num, since sugars have their auth_seq_num reused as sugar number... sigh.
resSeq = pdbx_branch_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
else if (type == "non-polymer") // same for non-polymers
resSeq = pdbx_nonpoly_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
else if (type == "polymer")
resSeq = pdbx_poly_seq_scheme.find1<int>("asym_id"_key == r.get<std::string>("label_asym_id") and "pdb_seq_num"_key == resSeq, "auth_seq_num");
if (chainID.length() > 1)
throw std::runtime_error("Chain ID " + chainID + " won't fit into a PDB file");
......@@ -3419,7 +3435,7 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
++numCoord;
auto ai = atom_site_anisotrop.find1(key("id") == id);
auto ai = atom_site_anisotrop.find_first(key("id") == id);
if (not ai.empty())
//
// auto ai = find_if(atom_site_anisotrop.begin(), atom_site_anisotrop.end(), [id](row_handle r) -> bool { return r["id"] == id; });
......
......@@ -4343,11 +4343,11 @@ void PDBFileParser::ConstructEntities()
{ "mon_id", hetID },
{ "ndb_seq_num", seqNr },
{ "pdb_seq_num", het.seqNum },
// { "auth_seq_num", het.seqNum }, // ????
{ "pdb_mon_id", hetID },
// { "auth_mon_id", hetID },
{ "pdb_strand_id", std::string{ het.chainID } },
{ "pdb_ins_code", iCode } });
{ "auth_seq_num", het.seqNum }, // Yes
{ "pdb_mon_id", hetID },
{ "auth_mon_id", hetID },
{ "pdb_strand_id", std::string{ het.chainID } },
{ "pdb_ins_code", iCode } });
// mapping needed?
mChainSeq2AsymSeq[std::make_tuple(het.chainID, het.seqNum, het.iCode)] = std::make_tuple(asymID, seqNr, false);
......
......@@ -1774,8 +1774,6 @@ _test.name
BOOST_AUTO_TEST_CASE(c3)
{
cif::VERBOSE = 1;
auto f = R"(data_TEST
#
loop_
......@@ -1811,6 +1809,43 @@ _test.name
BOOST_CHECK_EQUAL(name, "aap");
}
BOOST_AUTO_TEST_CASE(c4)
{
auto f = R"(data_TEST
#
loop_
_test.id
_test.name
1 aap
2 noot
3 mies
4 .
5 ?
)"_cf;
auto &db = f.front();
// query tests
BOOST_TEST(db["test"].find_max<int>("id") == 5);
BOOST_TEST(db["test"].find_max<int>("id", cif::key("name") != cif::null) == 3);
BOOST_TEST(db["test"].find_min<int>("id") == 1);
BOOST_TEST(db["test"].find_min<int>("id", cif::key("name") == cif::null) == 4);
// count tests
BOOST_TEST(db["test"].count(cif::all()) == 5);
BOOST_TEST(db["test"].count(cif::key("name") != cif::null) == 3);
BOOST_TEST(db["test"].count(cif::key("name") == cif::null) == 2);
// find_first tests
BOOST_TEST(db["test"].find_first<int>(cif::key("id") == 1, "id") == 1);
BOOST_TEST(db["test"].find_first<int>(cif::all(), "id") == 1);
// find1 tests
BOOST_TEST(db["test"].find1<int>(cif::key("id") == 1, "id") == 1);
BOOST_CHECK_THROW(db["test"].find1<int>(cif::all(), "id"), cif::multiple_results_error);
}
// --------------------------------------------------------------------
// rename test
......
......@@ -6,7 +6,7 @@ set -e
euid=${EUID:-$(id -u)}
if [ "${euid}" -ne 0 ] ; then
then echo "Please run as root"
echo "Please run as root"
exit
fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment