mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 22:14:24 +08:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaa5032e11 | ||
|
|
8400247674 | ||
|
|
08e1b197ac | ||
|
|
20971e1ee9 | ||
|
|
ce6a953eff | ||
|
|
87c20c26ec | ||
|
|
025ad93d06 | ||
|
|
e98fe2608a | ||
|
|
0399d99ca6 | ||
|
|
71b24a678e | ||
|
|
dc03cb6a70 | ||
|
|
de9b33a918 | ||
|
|
56c75490f2 | ||
|
|
20695404c1 |
2
.github/workflows/build-documentation.yml
vendored
2
.github/workflows/build-documentation.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
|
||||
- name: Run Sphinx
|
||||
run: |
|
||||
cmake --build ${{ steps.strings.outputs.build-output-dir }} --target Sphinx-libcifpp
|
||||
cmake --build ${{ steps.strings.outputs.build-output-dir }} --target Sphinx-cifpp
|
||||
ls -l ${{ steps.strings.outputs.build-output-dir }}
|
||||
ls -l ${{ steps.strings.outputs.build-output-dir }}/docs/sphinx
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ endif()
|
||||
# set the project name
|
||||
project(
|
||||
libcifpp
|
||||
VERSION 10.0.3
|
||||
VERSION 10.0.4
|
||||
LANGUAGES CXX C)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Version 10.0.4
|
||||
- Fixed find_by_value in the index of a category,
|
||||
avoid swapping columns in the search keys
|
||||
|
||||
Version 10.0.3
|
||||
- Clear pdbx_nonpoly_scheme before filling it in reconstruction
|
||||
- Changed handling of numbers with a preceding plus character,
|
||||
these are now stored as strings to avoid inadvertently
|
||||
mutilating phone numbers.
|
||||
|
||||
Version 10.0.2
|
||||
- Fixed regression in reconstruction introduced in 10.0.1
|
||||
|
||||
@@ -331,8 +331,11 @@ class item_value
|
||||
case TEXT:
|
||||
{
|
||||
auto sv = m_data.sv();
|
||||
auto sp = sv.data();
|
||||
if (*sp == '+')
|
||||
++sp;
|
||||
int64_t v;
|
||||
auto &&[ptr, ec] = from_chars(sv.data(), sv.data() + sv.length(), v);
|
||||
auto &&[ptr, ec] = from_chars(sp, sv.data() + sv.length(), v);
|
||||
if (ec != std::errc{})
|
||||
throw std::system_error(std::make_error_code(ec));
|
||||
if (ptr != sv.data() + sv.length())
|
||||
@@ -361,8 +364,11 @@ class item_value
|
||||
case TEXT:
|
||||
{
|
||||
auto sv = m_data.sv();
|
||||
auto sp = sv.data();
|
||||
if (*sp == '+')
|
||||
++sp;
|
||||
double v;
|
||||
auto &&[ptr, ec] = from_chars(sv.data(), sv.data() + sv.length(), v);
|
||||
auto &&[ptr, ec] = from_chars(sp, sv.data() + sv.length(), v);
|
||||
if (ec != std::errc{})
|
||||
throw std::system_error(std::make_error_code(ec));
|
||||
if (ptr != sv.data() + sv.length())
|
||||
|
||||
@@ -122,7 +122,7 @@ class atom
|
||||
|
||||
// const compound *compound() const;
|
||||
|
||||
[[nodiscard]] const item_value &get_property(std::string_view name) const;
|
||||
[[nodiscard]] const item_handle get_property(std::string_view name) const;
|
||||
void set_property(const std::string_view name, item_value value);
|
||||
|
||||
row_handle row()
|
||||
@@ -227,7 +227,7 @@ class atom
|
||||
explicit operator bool() const { return m_impl.operator bool(); }
|
||||
|
||||
/// \brief Return the item named @a name in the _atom_site category for this atom
|
||||
[[nodiscard]] const item_value &get_property_value(std::string_view name) const
|
||||
[[nodiscard]] const item_handle get_property_value(std::string_view name) const
|
||||
{
|
||||
if (not m_impl)
|
||||
throw std::logic_error("Error trying to fetch a property from an uninitialized atom");
|
||||
|
||||
105
src/category.cpp
105
src/category.cpp
@@ -118,6 +118,7 @@ class row_comparator
|
||||
|
||||
for (const auto &[k, f] : m_comparator)
|
||||
{
|
||||
assert(cat.get_item_name(k) == ai->name);
|
||||
d = f(ai->value, rhb[k].value());
|
||||
|
||||
if (d != 0)
|
||||
@@ -363,10 +364,9 @@ row *category_index::find_by_value(const category &cat, const category::key_type
|
||||
// sort the values in k first
|
||||
|
||||
category::key_type k2;
|
||||
for (auto &f : cat.key_item_indices())
|
||||
auto cv = cat.get_cat_validator();
|
||||
for (auto &fld : cv->m_keys)
|
||||
{
|
||||
auto fld = cat.get_item_name(f);
|
||||
|
||||
auto ki = std::ranges::find_if(k, [&fld](auto &i)
|
||||
{ return i.name == fld; });
|
||||
if (ki == k.end())
|
||||
@@ -614,11 +614,11 @@ void category::drop_empty_items()
|
||||
{
|
||||
std::vector<bool> is_empty(get_item_count(), true);
|
||||
|
||||
for (auto row : *this)
|
||||
for (size_t ix = 0; ix < get_item_count(); ++ix)
|
||||
{
|
||||
for (size_t ix = 0; ix < get_item_count(); ++ix)
|
||||
for (auto row : *this)
|
||||
{
|
||||
if (is_empty[ix] and not row[ix].empty())
|
||||
if (not row[ix].empty())
|
||||
{
|
||||
is_empty[ix] = false;
|
||||
break;
|
||||
@@ -759,14 +759,10 @@ void category::set_validator(const validator *v, datablock &db)
|
||||
if (not v.is_number())
|
||||
{
|
||||
// Try cast the value to a number and throw in case of failure
|
||||
try
|
||||
{
|
||||
if (auto sv = v.sv(); sv.find_first_of(".eE") == std::string_view::npos)
|
||||
v.cast_to_int();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
else
|
||||
v.cast_to_float();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1616,7 +1612,6 @@ void category::update_value(row *row, uint16_t item, item_value value, bool upda
|
||||
}
|
||||
else if (ec)
|
||||
throw validation_exception(ec, m_name, m_items[item].m_name);
|
||||
|
||||
}
|
||||
|
||||
// If the item is part of the Key for this category, remove it from the index
|
||||
@@ -2204,7 +2199,7 @@ void category::write_cif(std::ostream &os, const std::vector<uint16_t> &order, b
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
offset = detail::write_value(os, s, offset, w, right_aligned[cix]/* iv->is_number() */);
|
||||
offset = detail::write_value(os, s, offset, w, right_aligned[cix] /* iv->is_number() */);
|
||||
|
||||
if (offset > 132)
|
||||
{
|
||||
@@ -2726,70 +2721,20 @@ bool category::operator==(const category &rhs) const
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
// set<std::string> item_namesA(a.items()), item_namesB(b.items());
|
||||
//
|
||||
// if (item_namesA != item_namesB)
|
||||
// std::cout << "Unequal number of items\n";
|
||||
std::set<std::string> keys;
|
||||
|
||||
const category_validator *catValidator = nullptr;
|
||||
|
||||
auto validator = a.get_validator();
|
||||
if (validator != nullptr)
|
||||
catValidator = validator->get_validator_for_category(a.name());
|
||||
|
||||
using compType = std::function<int(std::string_view, std::string_view)>;
|
||||
std::vector<std::tuple<std::string, compType>> item_names;
|
||||
std::vector<std::string> keys;
|
||||
std::vector<std::size_t> keyIx;
|
||||
|
||||
if (catValidator == nullptr)
|
||||
for (const auto &items : { a.get_items(), b.get_items()})
|
||||
{
|
||||
for (auto &item_name : a.get_items())
|
||||
{
|
||||
item_names.emplace_back(item_name, [](std::string_view va, std::string_view vb)
|
||||
{ return va.compare(vb); });
|
||||
keyIx.push_back(keys.size());
|
||||
keys.push_back(item_name);
|
||||
}
|
||||
for (auto &item_name : items)
|
||||
keys.insert(item_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
keys = catValidator->m_keys;
|
||||
|
||||
for (auto &item_name : a.key_items())
|
||||
{
|
||||
auto iv = catValidator->get_validator_for_item(item_name);
|
||||
if (iv == nullptr)
|
||||
throw std::runtime_error("missing item validator");
|
||||
auto tv = iv->m_type;
|
||||
if (tv == nullptr)
|
||||
throw std::runtime_error("missing type validator");
|
||||
item_names.emplace_back(item_name, [tv](auto &&a1, auto &&a2)
|
||||
{ return tv->compare(std::forward<decltype(a1)>(a1), std::forward<decltype(a2)>(a2)); });
|
||||
|
||||
auto pred = [item_name](const std::string &s) -> bool
|
||||
{
|
||||
return cif::iequals(item_name, s) == 0;
|
||||
};
|
||||
if (std::ranges::find_if(keys, pred) == keys.end())
|
||||
keyIx.push_back(item_names.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// a.reorderByIndex();
|
||||
// b.reorderByIndex();
|
||||
|
||||
auto rowEqual = [&](const_row_handle &a, const_row_handle &b)
|
||||
{
|
||||
int d = 0;
|
||||
|
||||
for (auto kix : keyIx)
|
||||
for (const auto &item_name : keys)
|
||||
{
|
||||
std::string item_name;
|
||||
compType compare;
|
||||
|
||||
std::tie(item_name, compare) = item_names[kix];
|
||||
|
||||
d = a[item_name].compare(b[item_name]);
|
||||
|
||||
if (d != 0)
|
||||
@@ -2810,28 +2755,6 @@ bool category::operator==(const category &rhs) const
|
||||
if (not rowEqual(ra, rb))
|
||||
return false;
|
||||
|
||||
std::vector<std::string> missingA, missingB, different;
|
||||
|
||||
for (auto &tt : item_names)
|
||||
{
|
||||
std::string item_name;
|
||||
compType compare;
|
||||
|
||||
std::tie(item_name, compare) = tt;
|
||||
|
||||
// make it an option to compare unapplicable to empty or something
|
||||
|
||||
// auto ta = ra[item_name].text();
|
||||
// if (ta == "." or ta == "?")
|
||||
// ta = "";
|
||||
// auto tb = rb[item_name].text();
|
||||
// if (tb == "." or tb == "?")
|
||||
// tb = "";
|
||||
|
||||
if (ra[item_name].compare(rb[item_name]) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
|
||||
@@ -799,8 +799,8 @@ void compound_factory::report_missing_compound(std::string_view compound_id)
|
||||
std::clog << "\n"
|
||||
<< cif::coloured("Configuration error:", white, red) << "\n\n"
|
||||
<< "The attempt to retrieve compound information for " << std::quoted(compound_id) << " failed.\n\n"
|
||||
<< "This information is searched for in a CCD file called components.cif or\n"
|
||||
<< "components.cif.gz which should be located in one of the following directories:\n\n";
|
||||
<< "This information is searched for in a CCD file called components.cif\n"
|
||||
<< "which should be located in one of the following directories:\n\n";
|
||||
|
||||
cif::list_data_directories(std::clog);
|
||||
|
||||
|
||||
@@ -129,9 +129,9 @@ namespace detail
|
||||
m_item_ix = *ix;
|
||||
m_icase = is_item_type_uchar(c, m_item_name);
|
||||
|
||||
if (c.get_cat_validator() != nullptr and
|
||||
c.key_item_indices().contains(m_item_ix) and
|
||||
c.key_item_indices().size() == 1)
|
||||
if (auto cv = c.get_cat_validator();
|
||||
cv != nullptr and cv->m_keys.size() == 1 and
|
||||
cv->m_keys.front() == m_item_name)
|
||||
{
|
||||
m_single_hit = c[{ { m_item_name, m_value } }];
|
||||
}
|
||||
|
||||
@@ -239,7 +239,12 @@ void item_value::cast_to_int()
|
||||
{
|
||||
auto s = sv();
|
||||
int64_t v;
|
||||
auto [ptr, ec] = cif::from_chars(s.data(), s.data() + s.size(), v);
|
||||
|
||||
auto sp = s.data();
|
||||
if (*sp == '+')
|
||||
++sp;
|
||||
|
||||
auto [ptr, ec] = cif::from_chars(sp, s.data() + s.size(), v);
|
||||
if (ec != std::errc{})
|
||||
throw std::system_error(std::make_error_code(ec), "attempt to cast value to integer failed");
|
||||
if (ptr != s.data() + s.size())
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "cif++/cif++.hpp"
|
||||
#include "cif++/item.hpp"
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -76,10 +77,10 @@ void atom::atom_impl::moveTo(const point &p)
|
||||
|
||||
// const compound *compound() const;
|
||||
|
||||
const item_value &atom::atom_impl::get_property(std::string_view name) const
|
||||
const item_handle atom::atom_impl::get_property(std::string_view name) const
|
||||
{
|
||||
if (auto rh = row(); rh)
|
||||
return rh[name].value();
|
||||
return rh[name];
|
||||
throw std::runtime_error(std::format("Missing property {} for atom", name));
|
||||
}
|
||||
|
||||
@@ -1911,7 +1912,13 @@ void structure::change_residue(residue &res, const std::string &newCompound,
|
||||
for (const auto &[a1, a2] : remappedAtoms)
|
||||
{
|
||||
auto i = std::ranges::find_if(atoms, [id = a1](const atom &a)
|
||||
{ return a.get_label_atom_id() == id; });
|
||||
{
|
||||
if (a.get_row())
|
||||
{
|
||||
auto ih = a.get_property_value("label_atom_id");
|
||||
return not ih.empty() and ih.get<std::string>() == id;
|
||||
}
|
||||
return false; });
|
||||
if (i == atoms.end())
|
||||
{
|
||||
if (VERBOSE >= 0)
|
||||
@@ -2170,29 +2177,50 @@ std::string structure::create_non_poly(const std::string &entity_id, const std::
|
||||
{
|
||||
auto atom_id = atom_site.get_unique_id("");
|
||||
|
||||
auto row = atom_site.emplace({ { "group_PDB", atom.get_property("group_PDB") },
|
||||
{ "id", atom_id },
|
||||
{ "type_symbol", atom.get_property_value("type_symbol") },
|
||||
{ "label_atom_id", atom.get_property_value("label_atom_id") },
|
||||
{ "label_alt_id", atom.get_property_value("label_alt_id") },
|
||||
{ "label_comp_id", comp_id },
|
||||
{ "label_asym_id", asym_id },
|
||||
{ "label_entity_id", entity_id },
|
||||
{ "label_seq_id", cif::item_value_type::INAPPLICABLE },
|
||||
{ "pdbx_PDB_ins_code", cif::item_value_type::MISSING },
|
||||
{ "Cartn_x", atom.get_property_value("Cartn_x") },
|
||||
{ "Cartn_y", atom.get_property_value("Cartn_y") },
|
||||
{ "Cartn_z", atom.get_property_value("Cartn_z") },
|
||||
{ "occupancy", atom.get_property_value("occupancy") },
|
||||
{ "B_iso_or_equiv", atom.get_property_value("B_iso_or_equiv") },
|
||||
{ "pdbx_formal_charge", atom.get_property_value("pdbx_formal_charge") },
|
||||
{ "auth_seq_id", "1" },
|
||||
{ "auth_comp_id", comp_id },
|
||||
{ "auth_asym_id", asym_id },
|
||||
{ "auth_atom_id", atom.get_property_value("label_atom_id") },
|
||||
{ "pdbx_PDB_model_num", m_model_nr } });
|
||||
cif::row_initializer data //
|
||||
{
|
||||
{ "id", atom_id },
|
||||
{ "label_comp_id", comp_id },
|
||||
{ "label_asym_id", asym_id },
|
||||
{ "label_entity_id", entity_id },
|
||||
{ "label_seq_id", cif::item_value_type::INAPPLICABLE },
|
||||
{ "pdbx_PDB_ins_code", cif::item_value_type::MISSING },
|
||||
{ "auth_seq_id", "1" },
|
||||
{ "auth_comp_id", comp_id },
|
||||
{ "auth_asym_id", asym_id },
|
||||
{ "pdbx_PDB_model_num", m_model_nr } //
|
||||
};
|
||||
|
||||
for (auto item : std::initializer_list<std::string>{
|
||||
// clang-format off
|
||||
"group_PDB",
|
||||
"type_symbol",
|
||||
"label_atom_id",
|
||||
"label_alt_id",
|
||||
"auth_atom_id",
|
||||
"Cartn_x",
|
||||
"Cartn_y",
|
||||
"Cartn_z",
|
||||
"occupancy",
|
||||
"B_iso_or_equiv",
|
||||
"pdbx_formal_charge"
|
||||
// clang-format on
|
||||
})
|
||||
{
|
||||
auto v = atom.get_property_value(item);
|
||||
if (not v.empty())
|
||||
data.push_back({ item, v.value() });
|
||||
else
|
||||
data.push_back({ item, cif::item_value_type::INAPPLICABLE });
|
||||
}
|
||||
|
||||
auto row = atom_site.emplace(std::move(data));
|
||||
|
||||
auto &newAtom = emplace_atom(std::make_shared<atom::atom_impl>(m_db, atom_id));
|
||||
|
||||
if (newAtom.get_property_value("auth_atom_id").empty() and not newAtom.get_property_value("label_atom_id").empty())
|
||||
newAtom.set_property("auth_atom_id", newAtom.get_property("label_atom_id"));
|
||||
|
||||
res.add_atom(newAtom);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "cif++/cif++.hpp"
|
||||
#include "cif++/utilities.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
@@ -635,15 +636,28 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
|
||||
if (result == CIFToken::VALUE_NUMERIC_INTEGER)
|
||||
{
|
||||
// Avoid interpreting phone numbers as integers, TODO: check if this is an issue
|
||||
auto [ptr, ec] = from_chars(m_token_buffer.data(), m_token_buffer.data() + m_token_buffer.size(), m_token_value_int);
|
||||
if (ec != std::errc{})
|
||||
error("Invalid integer value: " + std::make_error_code(ec).message());
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::clog << "Invalid integer value: " << std::make_error_code(ec).message() << '\n';
|
||||
|
||||
result = CIFToken::VALUE_CHARSTRING;
|
||||
m_token_value = std::string_view(m_token_buffer.data(), m_token_buffer.size());
|
||||
}
|
||||
}
|
||||
else if (result == CIFToken::VALUE_NUMERIC_FLOAT)
|
||||
{
|
||||
auto [ptr, ec] = from_chars(m_token_buffer.data(), m_token_buffer.data() + m_token_buffer.size(), m_token_value_float);
|
||||
if (ec != std::errc{})
|
||||
error("Invalid integer value: " + std::make_error_code(ec).message());
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::clog << "Invalid floating point value: " << std::make_error_code(ec).message() << '\n';
|
||||
|
||||
result = CIFToken::VALUE_CHARSTRING;
|
||||
m_token_value = std::string_view(m_token_buffer.data(), m_token_buffer.size());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1811,13 +1811,10 @@ void WriteRemark3Phenix(std::ostream &pdbFile, const datablock &db)
|
||||
void WriteRemark3XPlor(std::ostream &pdbFile, const datablock &db)
|
||||
{
|
||||
auto refine = db["refine"].front();
|
||||
auto ls_shell = db["refine_ls_shell"].front();
|
||||
auto hist = db["refine_hist"].front();
|
||||
auto reflns = db["reflns"].front();
|
||||
auto analyze = db["refine_analyze"].front();
|
||||
auto &ls_restr = db["refine_ls_restr"];
|
||||
auto ls_restr_ncs = db["refine_ls_restr_ncs"].front();
|
||||
auto pdbx_xplor_file = db["pdbx_xplor_file"].front();
|
||||
|
||||
pdbFile << RM3("") << '\n'
|
||||
<< RM3(" DATA USED IN REFINEMENT.") << '\n'
|
||||
@@ -1837,7 +1834,11 @@ void WriteRemark3XPlor(std::ostream &pdbFile, const datablock &db)
|
||||
<< RM3(" FREE R VALUE : ", 7, 3) << Ff(refine, "ls_R_factor_R_free") << '\n'
|
||||
<< RM3(" FREE R VALUE TEST SET SIZE (%) : ", 7, 3) << Ff(refine, "ls_percent_reflns_R_free") << '\n'
|
||||
<< RM3(" FREE R VALUE TEST SET COUNT : ", 12, 6) << Fi(refine, "ls_number_reflns_R_free") << '\n'
|
||||
<< RM3(" ESTIMATED ERROR OF FREE R VALUE : ", 7, 3) << Ff(refine, "ls_R_factor_R_free_error") << '\n'
|
||||
<< RM3(" ESTIMATED ERROR OF FREE R VALUE : ", 7, 3) << Ff(refine, "ls_R_factor_R_free_error") << '\n';
|
||||
if (not db["refine_ls_shell"].empty())
|
||||
{
|
||||
auto ls_shell = db["refine_ls_shell"].front();
|
||||
pdbFile
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" FIT IN THE HIGHEST RESOLUTION BIN.") << '\n'
|
||||
@@ -1850,60 +1851,68 @@ void WriteRemark3XPlor(std::ostream &pdbFile, const datablock &db)
|
||||
<< RM3(" BIN FREE R VALUE : ", 7, 3) << Ff(ls_shell, "R_factor_R_free") << '\n'
|
||||
<< RM3(" BIN FREE R VALUE TEST SET SIZE (%) : ", 5, 1) << Ff(ls_shell, "percent_reflns_R_free") << '\n'
|
||||
<< RM3(" BIN FREE R VALUE TEST SET COUNT : ", 12, 6) << Fi(ls_shell, "number_reflns_R_free") << '\n'
|
||||
<< RM3(" ESTIMATED ERROR OF BIN FREE R VALUE : ", 7, 3) << Ff(ls_shell, "R_factor_R_free_error") << '\n'
|
||||
<< RM3(" ESTIMATED ERROR OF BIN FREE R VALUE : ", 7, 3) << Ff(ls_shell, "R_factor_R_free_error") << '\n';
|
||||
}
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT.") << '\n'
|
||||
<< RM3(" PROTEIN ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_protein") << '\n'
|
||||
<< RM3(" NUCLEIC ACID ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_nucleic_acid") << '\n'
|
||||
<< RM3(" HETEROGEN ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_ligand") << '\n'
|
||||
<< RM3(" SOLVENT ATOMS : ", 12, 6) << Fi(hist, "number_atoms_solvent") << '\n'
|
||||
pdbFile
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" NUMBER OF NON-HYDROGEN ATOMS USED IN REFINEMENT.") << '\n'
|
||||
<< RM3(" PROTEIN ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_protein") << '\n'
|
||||
<< RM3(" NUCLEIC ACID ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_nucleic_acid") << '\n'
|
||||
<< RM3(" HETEROGEN ATOMS : ", 12, 6) << Fi(hist, "pdbx_number_atoms_ligand") << '\n'
|
||||
<< RM3(" SOLVENT ATOMS : ", 12, 6) << Fi(hist, "number_atoms_solvent") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" B VALUES.") << '\n'
|
||||
<< RM3(" FROM WILSON PLOT (A**2) : ", 7, 2) << Ff(reflns, "B_iso_Wilson_estimate") << '\n'
|
||||
<< RM3(" MEAN B VALUE (OVERALL, A**2) : ", 7, 2) << Ff(refine, "B_iso_mean") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" B VALUES.") << '\n'
|
||||
<< RM3(" FROM WILSON PLOT (A**2) : ", 7, 2) << Ff(reflns, "B_iso_Wilson_estimate") << '\n'
|
||||
<< RM3(" MEAN B VALUE (OVERALL, A**2) : ", 7, 2) << Ff(refine, "B_iso_mean") << '\n'
|
||||
|
||||
<< RM3(" OVERALL ANISOTROPIC B VALUE.") << '\n'
|
||||
<< RM3(" B11 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][1]") << '\n'
|
||||
<< RM3(" B22 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[2][2]") << '\n'
|
||||
<< RM3(" B33 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[3][3]") << '\n'
|
||||
<< RM3(" B12 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][2]") << '\n'
|
||||
<< RM3(" B13 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][3]") << '\n'
|
||||
<< RM3(" B23 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[2][3]") << '\n'
|
||||
<< RM3(" OVERALL ANISOTROPIC B VALUE.") << '\n'
|
||||
<< RM3(" B11 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][1]") << '\n'
|
||||
<< RM3(" B22 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[2][2]") << '\n'
|
||||
<< RM3(" B33 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[3][3]") << '\n'
|
||||
<< RM3(" B12 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][2]") << '\n'
|
||||
<< RM3(" B13 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[1][3]") << '\n'
|
||||
<< RM3(" B23 (A**2) : ", -7, 2) << Ff(refine, "aniso_B[2][3]") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ESTIMATED COORDINATE ERROR.") << '\n'
|
||||
<< RM3(" ESD FROM LUZZATI PLOT (A) : ", 7, 2) << Ff(analyze, "Luzzati_coordinate_error_obs") << '\n'
|
||||
<< RM3(" ESD FROM SIGMAA (A) : ", 7, 2) << Ff(analyze, "Luzzati_sigma_a_obs") << '\n'
|
||||
<< RM3(" LOW RESOLUTION CUTOFF (A) : ", 7, 2) << Ff(analyze, "Luzzati_d_res_low_obs") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ESTIMATED COORDINATE ERROR.") << '\n'
|
||||
<< RM3(" ESD FROM LUZZATI PLOT (A) : ", 7, 2) << Ff(analyze, "Luzzati_coordinate_error_obs") << '\n'
|
||||
<< RM3(" ESD FROM SIGMAA (A) : ", 7, 2) << Ff(analyze, "Luzzati_sigma_a_obs") << '\n'
|
||||
<< RM3(" LOW RESOLUTION CUTOFF (A) : ", 7, 2) << Ff(analyze, "Luzzati_d_res_low_obs") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" CROSS-VALIDATED ESTIMATED COORDINATE ERROR.") << '\n'
|
||||
<< RM3(" ESD FROM C-V LUZZATI PLOT (A) : ", 7, 2) << Ff(analyze, "Luzzati_coordinate_error_free") << '\n'
|
||||
<< RM3(" ESD FROM C-V SIGMAA (A) : ", 7, 2) << Ff(analyze, "Luzzati_sigma_a_free") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" CROSS-VALIDATED ESTIMATED COORDINATE ERROR.") << '\n'
|
||||
<< RM3(" ESD FROM C-V LUZZATI PLOT (A) : ", 7, 2) << Ff(analyze, "Luzzati_coordinate_error_free") << '\n'
|
||||
<< RM3(" ESD FROM C-V SIGMAA (A) : ", 7, 2) << Ff(analyze, "Luzzati_sigma_a_free") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" RMS DEVIATIONS FROM IDEAL VALUES.") << '\n'
|
||||
<< RM3(" BOND LENGTHS (A) : ", 7, 3) << Ff(ls_restr, key("type") == "x_bond_d", "dev_ideal") << '\n'
|
||||
<< RM3(" BOND ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_angle_deg", "dev_ideal") << '\n'
|
||||
<< RM3(" DIHEDRAL ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_dihedral_angle_d", "dev_ideal") << '\n'
|
||||
<< RM3(" IMPROPER ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_improper_angle_d", "dev_ideal") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" RMS DEVIATIONS FROM IDEAL VALUES.") << '\n'
|
||||
<< RM3(" BOND LENGTHS (A) : ", 7, 3) << Ff(ls_restr, key("type") == "x_bond_d", "dev_ideal") << '\n'
|
||||
<< RM3(" BOND ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_angle_deg", "dev_ideal") << '\n'
|
||||
<< RM3(" DIHEDRAL ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_dihedral_angle_d", "dev_ideal") << '\n'
|
||||
<< RM3(" IMPROPER ANGLES (DEGREES) : ", 7, 2) << Ff(ls_restr, key("type") == "x_improper_angle_d", "dev_ideal") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ISOTROPIC THERMAL MODEL : ") << Fs(refine, "pdbx_isotropic_thermal_model") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ISOTROPIC THERMAL MODEL : ") << Fs(refine, "pdbx_isotropic_thermal_model") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ISOTROPIC THERMAL FACTOR RESTRAINTS. RMS SIGMA") << '\n'
|
||||
<< RM3(" MAIN-CHAIN BOND (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_mcbond_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_mcbond_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" MAIN-CHAIN ANGLE (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_mcangle_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_mcangle_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" SIDE-CHAIN BOND (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_scbond_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_scbond_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" SIDE-CHAIN ANGLE (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_scangle_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_scangle_it", "dev_ideal_target") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3("") << '\n'
|
||||
<< RM3(" ISOTROPIC THERMAL FACTOR RESTRAINTS. RMS SIGMA") << '\n'
|
||||
<< RM3(" MAIN-CHAIN BOND (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_mcbond_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_mcbond_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" MAIN-CHAIN ANGLE (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_mcangle_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_mcangle_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" SIDE-CHAIN BOND (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_scbond_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_scbond_it", "dev_ideal_target") << '\n'
|
||||
<< RM3(" SIDE-CHAIN ANGLE (A**2) : ", 6, 2) << Ff(ls_restr, key("type") == "x_scangle_it", "dev_ideal") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr, key("type") == "x_scangle_it", "dev_ideal_target") << '\n'
|
||||
<< RM3("") << '\n';
|
||||
|
||||
if (not db["refine_ls_restr_ncs"].empty())
|
||||
{
|
||||
auto ls_restr_ncs = db["refine_ls_restr_ncs"].front();
|
||||
|
||||
pdbFile
|
||||
<< RM3(" NCS MODEL : ") << Fs(ls_restr_ncs, "ncs_model_details") << '\n'
|
||||
|
||||
<< RM3("") << '\n'
|
||||
@@ -1913,7 +1922,14 @@ void WriteRemark3XPlor(std::ostream &pdbFile, const datablock &db)
|
||||
<< RM3(" GROUP 1 POSITIONAL (A) : ", 4, 2) << Ff(ls_restr_ncs, "rms_dev_position") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr_ncs, "weight_position") << SEP("; ", 6, 2) << '\n'
|
||||
<< RM3(" GROUP 1 B-FACTOR (A**2) : ", 4, 2) << Ff(ls_restr_ncs, "rms_dev_B_iso") << SEP("; ", 6, 2)
|
||||
<< Ff(ls_restr_ncs, "weight_B_iso") << SEP("; ", 6, 2) << '\n'
|
||||
<< Ff(ls_restr_ncs, "weight_B_iso") << SEP("; ", 6, 2) << '\n';
|
||||
}
|
||||
|
||||
if (not db["pdbx_xplor_file"].empty())
|
||||
{
|
||||
auto pdbx_xplor_file = db["pdbx_xplor_file"].front();
|
||||
|
||||
pdbFile
|
||||
|
||||
// TODO: using only files from serial_no 1 here
|
||||
<< RM3("") << '\n'
|
||||
@@ -1921,6 +1937,7 @@ void WriteRemark3XPlor(std::ostream &pdbFile, const datablock &db)
|
||||
<< RM3(" TOPOLOGY FILE 1 : ") << Fs(pdbx_xplor_file, "topol_file") << '\n'
|
||||
|
||||
<< RM3("") << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRemark3NuclSQ(std::ostream &pdbFile, const datablock &db)
|
||||
@@ -2258,25 +2275,28 @@ void WriteRemark200(std::ostream &pdbFile, const datablock &db)
|
||||
std::string iis = cifSoftware(db, eDataReduction);
|
||||
std::string dss = cifSoftware(db, eDataScaling);
|
||||
|
||||
auto source = diffrn_source["source"].get<std::string>();
|
||||
std::string synchrotron, type;
|
||||
|
||||
if (source.empty())
|
||||
synchrotron = "NULL";
|
||||
else if (iequals(source, "SYNCHROTRON"))
|
||||
std::string source, synchrotron, type;
|
||||
if (not diffrn_source.empty())
|
||||
{
|
||||
synchrotron = "Y";
|
||||
source = diffrn_source["pdbx_synchrotron_site"].get<std::string>();
|
||||
source = diffrn_source["source"].get<std::string>();
|
||||
|
||||
if (source.empty())
|
||||
source = "NULL";
|
||||
type = "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
synchrotron = "N";
|
||||
type = diffrn_source["type"].get<std::string>();
|
||||
if (type.empty())
|
||||
synchrotron = "NULL";
|
||||
else if (iequals(source, "SYNCHROTRON"))
|
||||
{
|
||||
synchrotron = "Y";
|
||||
source = diffrn_source["pdbx_synchrotron_site"].get<std::string>();
|
||||
if (source.empty())
|
||||
source = "NULL";
|
||||
type = "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
synchrotron = "N";
|
||||
type = diffrn_source["type"].get<std::string>();
|
||||
if (type.empty())
|
||||
type = "NULL";
|
||||
}
|
||||
}
|
||||
|
||||
if (source.empty())
|
||||
@@ -2343,7 +2363,7 @@ void WriteRemark200(std::ostream &pdbFile, const datablock &db)
|
||||
|
||||
for (auto &t : kTail)
|
||||
{
|
||||
auto s = t.r[t.field].get<std::string>();
|
||||
auto s = t.r.empty() ? "" : t.r[t.field].get<std::string>();
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
@@ -2384,6 +2404,9 @@ void WriteRemark280(std::ostream &pdbFile, const datablock &db)
|
||||
<< RM("MATTHEWS COEFFICIENT, VM (ANGSTROMS**3/DA): ", 6, 2) << Ff(exptl_crystal, "density_Matthews") << '\n'
|
||||
<< RM("") << '\n';
|
||||
|
||||
if (exptl_crystal_grow.empty())
|
||||
continue;
|
||||
|
||||
std::vector<std::string> conditions;
|
||||
auto add = [&conditions](const std::string c)
|
||||
{
|
||||
@@ -3341,9 +3364,9 @@ void WriteCrystallographic(std::ostream &pdbFile, const datablock &db)
|
||||
if (r)
|
||||
{
|
||||
auto symmetry = r["space_group_name_H-M"].get<std::string>();
|
||||
|
||||
|
||||
r = db["cell"].find_first(key("entry_id") == db.name());
|
||||
|
||||
|
||||
pdbFile << std::format("CRYST1{:9.3f}{:9.3f}{:9.3f}{:7.2f}{:7.2f}{:7.2f} {:<11.11s}{:4}", r["length_a"].get<double>(), r["length_b"].get<double>(), r["length_c"].get<double>(), r["angle_alpha"].get<double>(), r["angle_beta"].get<double>(), r["angle_gamma"].get<double>(), symmetry, r["Z_PDB"].get<int>()) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "cif++/cif++.hpp"
|
||||
#include "cif++/validate.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -1662,7 +1663,7 @@ bool reconstruct_pdbx(file &file, const validator &validator)
|
||||
if (not iv)
|
||||
{
|
||||
// Drop this item
|
||||
cat.remove_item(item_name);
|
||||
// cat.remove_item(item_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1691,6 +1692,13 @@ bool reconstruct_pdbx(file &file, const validator &validator)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ec == cif::make_error_code(cif::validation_error::value_is_not_in_enumeration_list))
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::clog << "Value (" << std::quoted(row[ix].str()) << ") for item " << item_name << " in category " << cat.name() << " is not valid since it is not in the list of allowed values\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VERBOSE > 0)
|
||||
std::clog << "Replacing value (" << std::quoted(row[ix].str()) << ") for item " << item_name << " in category " << cat.name() << " since it does not validate: " << ec.message() << "\n";
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3664,5 +3664,63 @@ HETATM 2 O O . HOH A 1 . ? 10.518 -1.781 0 1 37.22 ? O HOH 2 D 1
|
||||
)");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("number-test-1")
|
||||
{
|
||||
auto data = R"(data_test
|
||||
_pdbx_contact_author.id 1
|
||||
_pdbx_contact_author.name_mi +98765432109
|
||||
)"_cf;
|
||||
|
||||
auto &db = data.front();
|
||||
db.load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
auto r = db["pdbx_contact_author"].front();
|
||||
CHECK(r["name_mi"].str() == "+98765432109");
|
||||
CHECK(r["name_mi"].get<int64_t>() == 98765432109);
|
||||
CHECK(r["name_mi"].get<double>() == 98765432109.0);
|
||||
}
|
||||
|
||||
TEST_CASE("number-test-2")
|
||||
{
|
||||
auto data = R"(data_test
|
||||
_pdbx_contact_author.id 1
|
||||
_pdbx_contact_author.name_mi '+98765432109'
|
||||
)"_cf;
|
||||
|
||||
auto &db = data.front();
|
||||
db.load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
auto r = db["pdbx_contact_author"].front();
|
||||
CHECK(r["name_mi"].str() == "+98765432109");
|
||||
CHECK(r["name_mi"].get<int64_t>() == 98765432109);
|
||||
CHECK(r["name_mi"].get<double>() == 98765432109.0);
|
||||
}// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("q-1")
|
||||
{
|
||||
auto data = R"(data_test
|
||||
_test.s
|
||||
;1234567890
|
||||
1234567890
|
||||
;
|
||||
)"_cf;
|
||||
|
||||
auto r = data.front()["test"].find(cif::key("s") == "1234567890\n1234567890");
|
||||
CHECK(r.size() == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("large-int-1")
|
||||
{
|
||||
auto data = R"(data_test
|
||||
_entry.id 82E4475FF8B27F36
|
||||
)"_cf;
|
||||
|
||||
auto &db = data.front();
|
||||
db.load_dictionary("mmcif_pdbx.dic");
|
||||
|
||||
auto r = db["entry"].front();
|
||||
|
||||
CHECK(r["id"].get<std::string>() == "82E4475FF8B27F36");
|
||||
}
|
||||
Reference in New Issue
Block a user