Commit c9719f87 by Maarten L. Hekkelman

Merge branch 'develop' into trunk

parents 1c9212c7 123d25f8
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
# set the project name # set the project name
project(cifpp VERSION 2.0.4 LANGUAGES CXX) project(cifpp VERSION 3.0.1 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
...@@ -173,10 +173,6 @@ set(CMAKE_THREAD_PREFER_PTHREAD) ...@@ -173,10 +173,6 @@ set(CMAKE_THREAD_PREFER_PTHREAD)
set(THREADS_PREFER_PTHREAD_FLAG) set(THREADS_PREFER_PTHREAD_FLAG)
find_package(Threads) find_package(Threads)
set(Boost_DETAILED_FAILURE_MSG ON)
if(NOT BUILD_SHARED_LIBS)
set(Boost_USE_STATIC_LIBS ON)
endif()
find_package(Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex program_options) find_package(Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex program_options)
if(NOT MSVC AND Boost_USE_STATIC_LIBS) if(NOT MSVC AND Boost_USE_STATIC_LIBS)
...@@ -186,16 +182,14 @@ endif() ...@@ -186,16 +182,14 @@ endif()
# Create a revision file, containing the current git version info # Create a revision file, containing the current git version info
find_package(Git) include(GetGitRevisionDescription)
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") option(GENERATE_CUSTOM_VERSION "Generate a custom version string" OFF)
include(GetGitRevisionDescription) if(GIT-NOTFOUND OR HEAD-HASH-NOTFOUND OR NOT GENERATE_CUSTOM_VERSION)
get_git_head_revision(REFSPEC COMMITHASH) get_git_head_revision(REFSPEC COMMITHASH)
# Generate our own version string # Generate our own version string
git_describe_working_tree(BUILD_VERSION_STRING --match=build --dirty) git_describe_working_tree(BUILD_VERSION_STRING --match=build --dirty)
else() else()
message(WARNING "Git not found, cannot set version info")
SET(BUILD_VERSION_STRING ${PROJECT_VERSION}) SET(BUILD_VERSION_STRING ${PROJECT_VERSION})
endif() endif()
...@@ -256,7 +250,6 @@ set(project_headers ...@@ -256,7 +250,6 @@ set(project_headers
${PROJECT_SOURCE_DIR}/include/cif++/CifUtils.hpp ${PROJECT_SOURCE_DIR}/include/cif++/CifUtils.hpp
${PROJECT_SOURCE_DIR}/include/cif++/CifValidator.hpp ${PROJECT_SOURCE_DIR}/include/cif++/CifValidator.hpp
${PROJECT_SOURCE_DIR}/include/cif++/Compound.hpp ${PROJECT_SOURCE_DIR}/include/cif++/Compound.hpp
${PROJECT_SOURCE_DIR}/include/cif++/Matrix.hpp
${PROJECT_SOURCE_DIR}/include/cif++/PDB2Cif.hpp ${PROJECT_SOURCE_DIR}/include/cif++/PDB2Cif.hpp
${PROJECT_SOURCE_DIR}/include/cif++/PDB2CifRemark3.hpp ${PROJECT_SOURCE_DIR}/include/cif++/PDB2CifRemark3.hpp
${PROJECT_SOURCE_DIR}/include/cif++/Point.hpp ${PROJECT_SOURCE_DIR}/include/cif++/Point.hpp
......
Version 3.0.0
- Replaced many strings in the API with string_view for
performance reasons.
- Upgraded mmcif::Structure
- various other small fixes
Version 2.0.4 Version 2.0.4
- Reverted a too strict test when reading cif files. - Reverted a too strict test when reading cif files.
......
/*- /*-
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
* *
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this * 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer * list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...@@ -29,150 +29,151 @@ ...@@ -29,150 +29,151 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <string>
#include <stdexcept> #include <stdexcept>
#include <string>
namespace mmcif namespace mmcif
{ {
enum AtomType : uint8_t enum AtomType : uint8_t
{ {
Nn = 0, // Unknown Nn = 0, // Unknown
H = 1, // Hydro­gen H = 1, // Hydro­gen
He = 2, // He­lium He = 2, // He­lium
Li = 3, // Lith­ium Li = 3, // Lith­ium
Be = 4, // Beryl­lium Be = 4, // Beryl­lium
B = 5, // Boron B = 5, // Boron
C = 6, // Carbon C = 6, // Carbon
N = 7, // Nitro­gen N = 7, // Nitro­gen
O = 8, // Oxy­gen O = 8, // Oxy­gen
F = 9, // Fluor­ine F = 9, // Fluor­ine
Ne = 10, // Neon Ne = 10, // Neon
Na = 11, // So­dium Na = 11, // So­dium
Mg = 12, // Magne­sium Mg = 12, // Magne­sium
Al = 13, // Alumin­ium Al = 13, // Alumin­ium
Si = 14, // Sili­con Si = 14, // Sili­con
P = 15, // Phos­phorus P = 15, // Phos­phorus
S = 16, // Sulfur S = 16, // Sulfur
Cl = 17, // Chlor­ine Cl = 17, // Chlor­ine
Ar = 18, // Argon Ar = 18, // Argon
K = 19, // Potas­sium K = 19, // Potas­sium
Ca = 20, // Cal­cium Ca = 20, // Cal­cium
Sc = 21, // Scan­dium Sc = 21, // Scan­dium
Ti = 22, // Tita­nium Ti = 22, // Tita­nium
V = 23, // Vana­dium V = 23, // Vana­dium
Cr = 24, // Chrom­ium Cr = 24, // Chrom­ium
Mn = 25, // Manga­nese Mn = 25, // Manga­nese
Fe = 26, // Iron Fe = 26, // Iron
Co = 27, // Cobalt Co = 27, // Cobalt
Ni = 28, // Nickel Ni = 28, // Nickel
Cu = 29, // Copper Cu = 29, // Copper
Zn = 30, // Zinc Zn = 30, // Zinc
Ga = 31, // Gallium Ga = 31, // Gallium
Ge = 32, // Germa­nium Ge = 32, // Germa­nium
As = 33, // Arsenic As = 33, // Arsenic
Se = 34, // Sele­nium Se = 34, // Sele­nium
Br = 35, // Bromine Br = 35, // Bromine
Kr = 36, // Kryp­ton Kr = 36, // Kryp­ton
Rb = 37, // Rubid­ium Rb = 37, // Rubid­ium
Sr = 38, // Stront­ium Sr = 38, // Stront­ium
Y = 39, // Yttrium Y = 39, // Yttrium
Zr = 40, // Zirco­nium Zr = 40, // Zirco­nium
Nb = 41, // Nio­bium Nb = 41, // Nio­bium
Mo = 42, // Molyb­denum Mo = 42, // Molyb­denum
Tc = 43, // Tech­netium Tc = 43, // Tech­netium
Ru = 44, // Ruthe­nium Ru = 44, // Ruthe­nium
Rh = 45, // Rho­dium Rh = 45, // Rho­dium
Pd = 46, // Pallad­ium Pd = 46, // Pallad­ium
Ag = 47, // Silver Ag = 47, // Silver
Cd = 48, // Cad­mium Cd = 48, // Cad­mium
In = 49, // Indium In = 49, // Indium
Sn = 50, // Tin Sn = 50, // Tin
Sb = 51, // Anti­mony Sb = 51, // Anti­mony
Te = 52, // Tellurium Te = 52, // Tellurium
I = 53, // Iodine I = 53, // Iodine
Xe = 54, // Xenon Xe = 54, // Xenon
Cs = 55, // Cae­sium Cs = 55, // Cae­sium
Ba = 56, // Ba­rium Ba = 56, // Ba­rium
La = 57, // Lan­thanum La = 57, // Lan­thanum
Hf = 72, // Haf­nium Hf = 72, // Haf­nium
Ta = 73, // Tanta­lum Ta = 73, // Tanta­lum
W = 74, // Tung­sten W = 74, // Tung­sten
Re = 75, // Rhe­nium Re = 75, // Rhe­nium
Os = 76, // Os­mium Os = 76, // Os­mium
Ir = 77, // Iridium Ir = 77, // Iridium
Pt = 78, // Plat­inum Pt = 78, // Plat­inum
Au = 79, // Gold Au = 79, // Gold
Hg = 80, // Mer­cury Hg = 80, // Mer­cury
Tl = 81, // Thallium Tl = 81, // Thallium
Pb = 82, // Lead Pb = 82, // Lead
Bi = 83, // Bis­muth Bi = 83, // Bis­muth
Po = 84, // Polo­nium Po = 84, // Polo­nium
At = 85, // Asta­tine At = 85, // Asta­tine
Rn = 86, // Radon Rn = 86, // Radon
Fr = 87, // Fran­cium Fr = 87, // Fran­cium
Ra = 88, // Ra­dium Ra = 88, // Ra­dium
Ac = 89, // Actin­ium Ac = 89, // Actin­ium
Rf = 104, // Ruther­fordium Rf = 104, // Ruther­fordium
Db = 105, // Dub­nium Db = 105, // Dub­nium
Sg = 106, // Sea­borgium Sg = 106, // Sea­borgium
Bh = 107, // Bohr­ium Bh = 107, // Bohr­ium
Hs = 108, // Has­sium Hs = 108, // Has­sium
Mt = 109, // Meit­nerium Mt = 109, // Meit­nerium
Ds = 110, // Darm­stadtium Ds = 110, // Darm­stadtium
Rg = 111, // Roent­genium Rg = 111, // Roent­genium
Cn = 112, // Coper­nicium Cn = 112, // Coper­nicium
Nh = 113, // Nihon­ium Nh = 113, // Nihon­ium
Fl = 114, // Flerov­ium Fl = 114, // Flerov­ium
Mc = 115, // Moscov­ium Mc = 115, // Moscov­ium
Lv = 116, // Liver­morium Lv = 116, // Liver­morium
Ts = 117, // Tenness­ine Ts = 117, // Tenness­ine
Og = 118, // Oga­nesson Og = 118, // Oga­nesson
Ce = 58, // Cerium Ce = 58, // Cerium
Pr = 59, // Praseo­dymium Pr = 59, // Praseo­dymium
Nd = 60, // Neo­dymium Nd = 60, // Neo­dymium
Pm = 61, // Prome­thium Pm = 61, // Prome­thium
Sm = 62, // Sama­rium Sm = 62, // Sama­rium
Eu = 63, // Europ­ium Eu = 63, // Europ­ium
Gd = 64, // Gadolin­ium Gd = 64, // Gadolin­ium
Tb = 65, // Ter­bium Tb = 65, // Ter­bium
Dy = 66, // Dyspro­sium Dy = 66, // Dyspro­sium
Ho = 67, // Hol­mium Ho = 67, // Hol­mium
Er = 68, // Erbium Er = 68, // Erbium
Tm = 69, // Thulium Tm = 69, // Thulium
Yb = 70, // Ytter­bium Yb = 70, // Ytter­bium
Lu = 71, // Lute­tium Lu = 71, // Lute­tium
Th = 90, // Thor­ium Th = 90, // Thor­ium
Pa = 91, // Protac­tinium Pa = 91, // Protac­tinium
U = 92, // Ura­nium U = 92, // Ura­nium
Np = 93, // Neptu­nium Np = 93, // Neptu­nium
Pu = 94, // Pluto­nium Pu = 94, // Pluto­nium
Am = 95, // Ameri­cium Am = 95, // Ameri­cium
Cm = 96, // Curium Cm = 96, // Curium
Bk = 97, // Berkel­ium Bk = 97, // Berkel­ium
Cf = 98, // Califor­nium Cf = 98, // Califor­nium
Es = 99, // Einstei­nium Es = 99, // Einstei­nium
Fm = 100, // Fer­mium Fm = 100, // Fer­mium
Md = 101, // Mende­levium Md = 101, // Mende­levium
No = 102, // Nobel­ium No = 102, // Nobel­ium
Lr = 103, // Lawren­cium Lr = 103, // Lawren­cium
D = 129, // Deuterium D = 129, // Deuterium
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// AtomTypeInfo // AtomTypeInfo
enum RadiusType { enum RadiusType
{
eRadiusCalculated, eRadiusCalculated,
eRadiusEmpirical, eRadiusEmpirical,
eRadiusCovalentEmpirical, eRadiusCovalentEmpirical,
...@@ -188,12 +189,12 @@ enum RadiusType { ...@@ -188,12 +189,12 @@ enum RadiusType {
struct AtomTypeInfo struct AtomTypeInfo
{ {
AtomType type; AtomType type;
std::string name; std::string name;
std::string symbol; std::string symbol;
float weight; float weight;
bool metal; bool metal;
float radii[eRadiusTypeCount]; float radii[eRadiusTypeCount];
}; };
extern const AtomTypeInfo kKnownAtoms[]; extern const AtomTypeInfo kKnownAtoms[];
...@@ -205,25 +206,25 @@ class AtomTypeTraits ...@@ -205,25 +206,25 @@ class AtomTypeTraits
{ {
public: public:
AtomTypeTraits(AtomType a); AtomTypeTraits(AtomType a);
AtomTypeTraits(const std::string& symbol); AtomTypeTraits(const std::string &symbol);
AtomType type() const { return mInfo->type; } AtomType type() const { return mInfo->type; }
std::string name() const { return mInfo->name; } std::string name() const { return mInfo->name; }
std::string symbol() const { return mInfo->symbol; } std::string symbol() const { return mInfo->symbol; }
float weight() const { return mInfo->weight; } float weight() const { return mInfo->weight; }
bool isMetal() const { return mInfo->metal; } bool isMetal() const { return mInfo->metal; }
static bool isElement(const std::string& symbol); static bool isElement(const std::string &symbol);
static bool isMetal(const std::string& symbol); static bool isMetal(const std::string &symbol);
float radius(RadiusType type = eRadiusSingleBond) const float radius(RadiusType type = eRadiusSingleBond) const
{ {
if (type >= eRadiusTypeCount) if (type >= eRadiusTypeCount)
throw std::invalid_argument("invalid radius requested"); throw std::invalid_argument("invalid radius requested");
return mInfo->radii[type] / 100.f; return mInfo->radii[type] / 100.f;
} }
// data type encapsulating the Waasmaier & Kirfel scattering factors // data type encapsulating the Waasmaier & Kirfel scattering factors
// in a simplified form (only a and b). // in a simplified form (only a and b).
// Added the electrion scattering factors as well // Added the electrion scattering factors as well
...@@ -231,15 +232,18 @@ class AtomTypeTraits ...@@ -231,15 +232,18 @@ class AtomTypeTraits
{ {
double a[6], b[6]; double a[6], b[6];
}; };
// to get the Cval and Siva values, use this constant as charge: // to get the Cval and Siva values, use this constant as charge:
enum { kWKSFVal = -99 }; enum
{
const SFData& wksf(int charge = 0) const; kWKSFVal = -99
const SFData& elsf() const; };
const SFData &wksf(int charge = 0) const;
const SFData &elsf() const;
private: private:
const struct AtomTypeInfo* mInfo; const struct AtomTypeInfo *mInfo;
}; };
} } // namespace mmcif
/*- /*-
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
* *
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this * 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer * list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...@@ -26,9 +26,9 @@ ...@@ -26,9 +26,9 @@
#pragma once #pragma once
#include <unordered_map>
#include <filesystem> #include <filesystem>
#include <stdexcept> #include <stdexcept>
#include <unordered_map>
#include "cif++/Structure.hpp" #include "cif++/Structure.hpp"
...@@ -38,39 +38,40 @@ namespace mmcif ...@@ -38,39 +38,40 @@ namespace mmcif
class BondMapException : public std::runtime_error class BondMapException : public std::runtime_error
{ {
public: public:
BondMapException(const std::string& msg) BondMapException(const std::string &msg)
: runtime_error(msg) {} : runtime_error(msg)
{
}
}; };
class BondMap class BondMap
{ {
public: public:
BondMap(const Structure& p); BondMap(const Structure &p);
BondMap(const BondMap&) = delete; BondMap(const BondMap &) = delete;
BondMap& operator=(const BondMap&) = delete; BondMap &operator=(const BondMap &) = delete;
bool operator()(const Atom& a, const Atom& b) const bool operator()(const Atom &a, const Atom &b) const
{ {
return isBonded(index.at(a.id()), index.at(b.id())); return isBonded(index.at(a.id()), index.at(b.id()));
} }
bool is1_4(const Atom& a, const Atom& b) const bool is1_4(const Atom &a, const Atom &b) const
{ {
uint32_t ixa = index.at(a.id()); uint32_t ixa = index.at(a.id());
uint32_t ixb = index.at(b.id()); uint32_t ixb = index.at(b.id());
return bond_1_4.count(key(ixa, ixb)); return bond_1_4.count(key(ixa, ixb));
} }
// links coming from the struct_conn records: // links coming from the struct_conn records:
std::vector<std::string> linked(const Atom& a) const; std::vector<std::string> linked(const Atom &a) const;
// This list of atomID's is comming from either CCD or the CCP4 dictionaries loaded // This list of atomID's is comming from either CCD or the CCP4 dictionaries loaded
static std::vector<std::string> atomIDsForCompound(const std::string& compoundID); static std::vector<std::string> atomIDsForCompound(const std::string &compoundID);
private:
private:
bool isBonded(uint32_t ai, uint32_t bi) const bool isBonded(uint32_t ai, uint32_t bi) const
{ {
return bond.count(key(ai, bi)) != 0; return bond.count(key(ai, bi)) != 0;
...@@ -82,20 +83,19 @@ class BondMap ...@@ -82,20 +83,19 @@ class BondMap
std::swap(a, b); std::swap(a, b);
return static_cast<uint64_t>(a) | (static_cast<uint64_t>(b) << 32); return static_cast<uint64_t>(a) | (static_cast<uint64_t>(b) << 32);
} }
std::tuple<uint32_t,uint32_t> dekey(uint64_t k) const std::tuple<uint32_t, uint32_t> dekey(uint64_t k) const
{ {
return std::make_tuple( return std::make_tuple(
static_cast<uint32_t>(k >> 32), static_cast<uint32_t>(k >> 32),
static_cast<uint32_t>(k) static_cast<uint32_t>(k));
);
} }
uint32_t dim; uint32_t dim;
std::unordered_map<std::string,uint32_t> index; std::unordered_map<std::string, uint32_t> index;
std::set<uint64_t> bond, bond_1_4; std::set<uint64_t> bond, bond_1_4;
std::map<std::string,std::set<std::string>> link; std::map<std::string, std::set<std::string>> link;
}; };
} } // namespace mmcif
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include <regex> #include <regex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <iomanip>
#include <shared_mutex>
#include <boost/format.hpp>
#include "cif++/CifUtils.hpp" #include "cif++/CifUtils.hpp"
...@@ -141,14 +145,27 @@ class Item ...@@ -141,14 +145,27 @@ class Item
public: public:
Item() {} Item() {}
Item(std::string_view name, char value)
: mName(name)
, mValue({ value })
{
}
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
Item(std::string_view name, const T& value, const char *fmt)
: mName(name)
, mValue((boost::format(fmt) % value).str())
{
}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
Item(const std::string &name, const T &value) Item(const std::string_view name, const T &value)
: mName(name) : mName(name)
, mValue(std::to_string(value)) , mValue(std::to_string(value))
{ {
} }
Item(const std::string &name, const std::string &value) Item(const std::string_view name, const std::string_view value)
: mName(name) : mName(name)
, mValue(value) , mValue(value)
{ {
...@@ -221,7 +238,7 @@ class Datablock ...@@ -221,7 +238,7 @@ class Datablock
using iterator = CategoryList::iterator; using iterator = CategoryList::iterator;
using const_iterator = CategoryList::const_iterator; using const_iterator = CategoryList::const_iterator;
Datablock(const std::string &name); Datablock(const std::string_view name);
~Datablock(); ~Datablock();
Datablock(const Datablock &) = delete; Datablock(const Datablock &) = delete;
...@@ -230,33 +247,31 @@ class Datablock ...@@ -230,33 +247,31 @@ class Datablock
std::string getName() const { return mName; } std::string getName() const { return mName; }
void setName(const std::string &n) { mName = n; } void setName(const std::string &n) { mName = n; }
std::string firstItem(const std::string &tag) const;
iterator begin() { return mCategories.begin(); } iterator begin() { return mCategories.begin(); }
iterator end() { return mCategories.end(); } iterator end() { return mCategories.end(); }
const_iterator begin() const { return mCategories.begin(); } const_iterator begin() const { return mCategories.begin(); }
const_iterator end() const { return mCategories.end(); } const_iterator end() const { return mCategories.end(); }
Category &operator[](const std::string &name); Category &operator[](std::string_view name);
std::tuple<iterator, bool> emplace(const std::string &name); std::tuple<iterator, bool> emplace(std::string_view name);
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
void setValidator(Validator *v); void setValidator(const Validator *v);
// this one only looks up a Category, returns nullptr if it does not exist // this one only looks up a Category, returns nullptr if it does not exist
const Category *get(const std::string &name) const; const Category *get(std::string_view name) const;
Category *get(const std::string &name); Category *get(std::string_view name);
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
void write(std::ostream &os, const std::vector<std::string> &order); void write(std::ostream &os, const std::vector<std::string> &order);
void write(std::ostream &os); void write(std::ostream &os);
// convenience function, add a line to the software category // convenience function, add a line to the software category
void add_software(const std::string &name, const std::string &classification, void add_software(const std::string_view name, const std::string &classification,
const std::string &versionNr, const std::string &versionDate); const std::string &versionNr, const std::string &versionDate);
friend bool operator==(const Datablock &lhs, const Datablock &rhs); friend bool operator==(const Datablock &lhs, const Datablock &rhs);
...@@ -264,9 +279,10 @@ class Datablock ...@@ -264,9 +279,10 @@ class Datablock
friend std::ostream& operator<<(std::ostream &os, const Datablock &data); friend std::ostream& operator<<(std::ostream &os, const Datablock &data);
private: private:
std::list<Category> mCategories; CategoryList mCategories; // LRU
mutable std::shared_mutex mLock;
std::string mName; std::string mName;
Validator *mValidator; const Validator *mValidator;
Datablock *mNext; Datablock *mNext;
}; };
...@@ -350,14 +366,14 @@ namespace detail ...@@ -350,14 +366,14 @@ namespace detail
private: private:
friend class ::cif::Row; friend class ::cif::Row;
ItemReference(const char *name, size_t column, Row &row) ItemReference(std::string_view name, size_t column, Row &row)
: mName(name) : mName(name)
, mColumn(column) , mColumn(column)
, mRow(row) , mRow(row)
{ {
} }
ItemReference(const char *name, size_t column, const Row &row) ItemReference(std::string_view name, size_t column, const Row &row)
: mName(name) : mName(name)
, mColumn(column) , mColumn(column)
, mRow(const_cast<Row &>(row)) , mRow(const_cast<Row &>(row))
...@@ -365,7 +381,7 @@ namespace detail ...@@ -365,7 +381,7 @@ namespace detail
{ {
} }
const char *mName; std::string_view mName;
size_t mColumn; size_t mColumn;
Row &mRow; Row &mRow;
bool mConst = false; bool mConst = false;
...@@ -746,16 +762,16 @@ class Row ...@@ -746,16 +762,16 @@ class Row
return detail::ItemReference(itemTag, column, *this); return detail::ItemReference(itemTag, column, *this);
} }
const detail::ItemReference operator[](const std::string &itemTag) const const detail::ItemReference operator[](std::string_view itemTag) const
{ {
size_t column = ColumnForItemTag(itemTag.c_str()); size_t column = ColumnForItemTag(itemTag);
return detail::ItemReference(itemTag.c_str(), column, *this); return detail::ItemReference(itemTag, column, *this);
} }
detail::ItemReference operator[](const std::string &itemTag) detail::ItemReference operator[](std::string_view itemTag)
{ {
size_t column = ColumnForItemTag(itemTag.c_str()); size_t column = ColumnForItemTag(itemTag);
return detail::ItemReference(itemTag.c_str(), column, *this); return detail::ItemReference(itemTag, column, *this);
} }
template <typename... Ts, size_t N> template <typename... Ts, size_t N>
...@@ -776,7 +792,7 @@ class Row ...@@ -776,7 +792,7 @@ class Row
} }
void assign(const std::vector<Item> &values); void assign(const std::vector<Item> &values);
void assign(const std::string &name, const std::string &value, bool updateLinked); void assign(std::string_view name, const std::string &value, bool updateLinked);
bool operator==(const Row &rhs) const bool operator==(const Row &rhs) const
{ {
...@@ -803,7 +819,7 @@ class Row ...@@ -803,7 +819,7 @@ class Row
static void swap(size_t column, ItemRow *a, ItemRow *b); static void swap(size_t column, ItemRow *a, ItemRow *b);
size_t ColumnForItemTag(const char *itemTag) const; size_t ColumnForItemTag(std::string_view itemTag) const;
mutable ItemRow *mData; mutable ItemRow *mData;
uint32_t mLineNr = 0; uint32_t mLineNr = 0;
...@@ -1169,11 +1185,11 @@ struct Empty ...@@ -1169,11 +1185,11 @@ struct Empty
struct Key struct Key
{ {
Key(const std::string &itemTag) explicit Key(const std::string &itemTag)
: mItemTag(itemTag) : mItemTag(itemTag)
{ {
} }
Key(const char *itemTag) explicit Key(const char *itemTag)
: mItemTag(itemTag) : mItemTag(itemTag)
{ {
} }
...@@ -1816,12 +1832,12 @@ class Category ...@@ -1816,12 +1832,12 @@ class Category
friend class Row; friend class Row;
friend class detail::ItemReference; friend class detail::ItemReference;
Category(Datablock &db, const std::string &name, Validator *Validator); Category(Datablock &db, const std::string_view name, const Validator *Validator);
Category(const Category &) = delete; Category(const Category &) = delete;
Category &operator=(const Category &) = delete; Category &operator=(const Category &) = delete;
~Category(); ~Category();
const std::string name() const { return mName; } const std::string &name() const { return mName; }
using iterator = iterator_impl<Row>; using iterator = iterator_impl<Row>;
using const_iterator = iterator_impl<const Row>; using const_iterator = iterator_impl<const Row>;
...@@ -2064,7 +2080,7 @@ class Category ...@@ -2064,7 +2080,7 @@ class Category
Datablock &db() { return mDb; } Datablock &db() { return mDb; }
void setValidator(Validator *v); void setValidator(const Validator *v);
iset fields() const; iset fields() const;
iset mandatoryFields() const; iset mandatoryFields() const;
...@@ -2077,8 +2093,8 @@ class Category ...@@ -2077,8 +2093,8 @@ class Category
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
// return index for known column, or the next available column index // return index for known column, or the next available column index
size_t getColumnIndex(const std::string &name) const; size_t getColumnIndex(std::string_view name) const;
bool hasColumn(const std::string &name) const; bool hasColumn(std::string_view name) const;
const std::string &getColumnName(size_t columnIndex) const; const std::string &getColumnName(size_t columnIndex) const;
std::vector<std::string> getColumnNames() const; std::vector<std::string> getColumnNames() const;
...@@ -2119,16 +2135,26 @@ class Category ...@@ -2119,16 +2135,26 @@ class Category
void write(std::ostream &os, const std::vector<std::string> &order); void write(std::ostream &os, const std::vector<std::string> &order);
void write(std::ostream &os, const std::vector<size_t> &order, bool includeEmptyColumns); void write(std::ostream &os, const std::vector<size_t> &order, bool includeEmptyColumns);
size_t addColumn(const std::string &name); size_t addColumn(std::string_view name);
struct Linked
{
Category *linked;
const ValidateLink *v;
};
void updateLinks();
Datablock &mDb; Datablock &mDb;
std::string mName; std::string mName;
Validator *mValidator; const Validator *mValidator;
const ValidateCategory *mCatValidator = nullptr; const ValidateCategory *mCatValidator = nullptr;
std::vector<ItemColumn> mColumns; std::vector<ItemColumn> mColumns;
ItemRow *mHead; ItemRow *mHead;
ItemRow *mTail; ItemRow *mTail;
class CatIndex *mIndex; class CatIndex *mIndex;
std::vector<Linked> mParentLinks, mChildLinks;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -2162,7 +2188,8 @@ class File ...@@ -2162,7 +2188,8 @@ class File
void loadDictionary(); // load the default dictionary, that is mmcifDdl in this case void loadDictionary(); // load the default dictionary, that is mmcifDdl in this case
void loadDictionary(const char *dict); // load one of the compiled in dictionaries void loadDictionary(const char *dict); // load one of the compiled in dictionaries
void loadDictionary(std::istream &is); // load dictionary from input stream
void setValidator(const Validator *v);
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
...@@ -2183,8 +2210,8 @@ class File ...@@ -2183,8 +2210,8 @@ class File
void append(Datablock *e); void append(Datablock *e);
Datablock *get(const std::string &name) const; Datablock *get(std::string_view name) const;
Datablock &operator[](const std::string &name); Datablock &operator[](std::string_view name);
struct iterator struct iterator
{ {
...@@ -2226,10 +2253,8 @@ class File ...@@ -2226,10 +2253,8 @@ class File
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
private: private:
void setValidator(Validator *v);
Datablock *mHead; Datablock *mHead;
Validator *mValidator; const Validator *mValidator;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include <stack>
#include <map> #include <map>
#include <stack>
namespace cif namespace cif
{ {
...@@ -39,7 +39,7 @@ namespace cif ...@@ -39,7 +39,7 @@ namespace cif
class CifParserError : public std::runtime_error class CifParserError : public std::runtime_error
{ {
public: public:
CifParserError(uint32_t lineNr, const std::string& message); CifParserError(uint32_t lineNr, const std::string &message);
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength; ...@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength;
extern const uint8_t kCharTraitsTable[128]; extern const uint8_t kCharTraitsTable[128];
enum CharTraitsMask: uint8_t { enum CharTraitsMask : uint8_t
{
kOrdinaryMask = 1 << 0, kOrdinaryMask = 1 << 0,
kNonBlankMask = 1 << 1, kNonBlankMask = 1 << 1,
kTextLeadMask = 1 << 2, kTextLeadMask = 1 << 2,
...@@ -75,13 +76,13 @@ inline bool isTextLead(int ch) ...@@ -75,13 +76,13 @@ inline bool isTextLead(int ch)
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0; return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0;
} }
inline bool isAnyPrint(int ch) inline bool isAnyPrint(int ch)
{ {
return ch == '\t' or return ch == '\t' or
(ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0); (ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0);
} }
inline bool isUnquotedString(const char* s) inline bool isUnquotedString(const char *s)
{ {
bool result = isOrdinary(*s++); bool result = isOrdinary(*s++);
while (result and *s != 0) while (result and *s != 0)
...@@ -94,11 +95,7 @@ inline bool isUnquotedString(const char* s) ...@@ -94,11 +95,7 @@ inline bool isUnquotedString(const char* s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string,std::string> splitTagName(const std::string& tag); using DatablockIndex = std::map<std::string, std::size_t>;
// --------------------------------------------------------------------
using DatablockIndex = std::map<std::string,std::size_t>;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// sac Parser, analogous to SAX Parser (simple api for xml) // sac Parser, analogous to SAX Parser (simple api for xml)
...@@ -106,15 +103,15 @@ using DatablockIndex = std::map<std::string,std::size_t>; ...@@ -106,15 +103,15 @@ using DatablockIndex = std::map<std::string,std::size_t>;
class SacParser class SacParser
{ {
public: public:
SacParser(std::istream& is, bool init = true); SacParser(std::istream &is, bool init = true);
virtual ~SacParser() {} virtual ~SacParser() {}
enum CIFToken enum CIFToken
{ {
eCIFTokenUnknown, eCIFTokenUnknown,
eCIFTokenEOF, eCIFTokenEOF,
eCIFTokenDATA, eCIFTokenDATA,
eCIFTokenLOOP, eCIFTokenLOOP,
eCIFTokenGLOBAL, eCIFTokenGLOBAL,
...@@ -124,7 +121,7 @@ class SacParser ...@@ -124,7 +121,7 @@ class SacParser
eCIFTokenValue, eCIFTokenValue,
}; };
static const char* kTokenName[]; static const char *kTokenName[];
enum CIFValueType enum CIFValueType
{ {
...@@ -137,40 +134,39 @@ class SacParser ...@@ -137,40 +134,39 @@ class SacParser
eCIFValueUnknown eCIFValueUnknown
}; };
static const char* kValueName[]; static const char *kValueName[];
int getNextChar(); int getNextChar();
void retract(); void retract();
void restart(); void restart();
CIFToken getNextToken(); CIFToken getNextToken();
void match(CIFToken token); void match(CIFToken token);
bool parseSingleDatablock(const std::string& datablock); bool parseSingleDatablock(const std::string &datablock);
DatablockIndex indexDatablocks(); DatablockIndex indexDatablocks();
bool parseSingleDatablock(const std::string& datablock, const DatablockIndex &index); bool parseSingleDatablock(const std::string &datablock, const DatablockIndex &index);
void parseFile(); void parseFile();
void parseGlobal(); void parseGlobal();
void parseDataBlock(); void parseDataBlock();
virtual void parseSaveFrame(); virtual void parseSaveFrame();
void parseDictionary(); void parseDictionary();
void error(const std::string& msg); void error(const std::string &msg);
// production methods, these are pure virtual here // production methods, these are pure virtual here
virtual void produceDatablock(const std::string& name) = 0; virtual void produceDatablock(const std::string &name) = 0;
virtual void produceCategory(const std::string& name) = 0; virtual void produceCategory(const std::string &name) = 0;
virtual void produceRow() = 0; virtual void produceRow() = 0;
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value) = 0; virtual void produceItem(const std::string &category, const std::string &item, const std::string &value) = 0;
protected: protected:
enum State enum State
{ {
eStateStart, eStateStart,
...@@ -185,21 +181,21 @@ class SacParser ...@@ -185,21 +181,21 @@ class SacParser
eStateTextField, eStateTextField,
eStateFloat = 100, eStateFloat = 100,
eStateInt = 110, eStateInt = 110,
// eStateNumericSuffix = 200, // eStateNumericSuffix = 200,
eStateValue = 300 eStateValue = 300
}; };
std::istream& mData; std::istream &mData;
// Parser state // Parser state
bool mValidate; bool mValidate;
uint32_t mLineNr; uint32_t mLineNr;
bool mBol; bool mBol;
int mState, mStart; int mState, mStart;
CIFToken mLookahead; CIFToken mLookahead;
std::string mTokenValue; std::string mTokenValue;
CIFValueType mTokenType; CIFValueType mTokenType;
std::stack<int> mBuffer; std::stack<int> mBuffer;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -207,18 +203,18 @@ class SacParser ...@@ -207,18 +203,18 @@ class SacParser
class Parser : public SacParser class Parser : public SacParser
{ {
public: public:
Parser(std::istream& is, File& f, bool init = true); Parser(std::istream &is, File &f, bool init = true);
virtual void produceDatablock(const std::string& name); virtual void produceDatablock(const std::string &name);
virtual void produceCategory(const std::string& name); virtual void produceCategory(const std::string &name);
virtual void produceRow(); virtual void produceRow();
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value); virtual void produceItem(const std::string &category, const std::string &item, const std::string &value);
protected: protected:
File& mFile; File &mFile;
Datablock* mDataBlock; Datablock *mDataBlock;
Datablock::iterator mCat; Datablock::iterator mCat;
Row mRow; Row mRow;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -226,23 +222,21 @@ class Parser : public SacParser ...@@ -226,23 +222,21 @@ class Parser : public SacParser
class DictParser : public Parser class DictParser : public Parser
{ {
public: public:
DictParser(Validator &validator, std::istream &is);
DictParser(Validator& validator, std::istream& is);
~DictParser(); ~DictParser();
void loadDictionary(); void loadDictionary();
private:
private:
virtual void parseSaveFrame(); virtual void parseSaveFrame();
bool collectItemTypes(); bool collectItemTypes();
void linkItems(); void linkItems();
Validator& mValidator; Validator &mValidator;
File mFile; File mFile;
struct DictParserDataImpl* mImpl; struct DictParserDataImpl *mImpl;
bool mCollectedItemTypes = false; bool mCollectedItemTypes = false;
}; };
} } // namespace cif
...@@ -67,8 +67,8 @@ std::string get_version_nr(); ...@@ -67,8 +67,8 @@ std::string get_version_nr();
// some basic utilities: Since we're using ASCII input only, we define for optimisation // some basic utilities: Since we're using ASCII input only, we define for optimisation
// our own case conversion routines. // our own case conversion routines.
bool iequals(const std::string &a, const std::string &b); bool iequals(std::string_view a, std::string_view b);
int icompare(const std::string &a, const std::string &b); int icompare(std::string_view a, std::string_view b);
bool iequals(const char *a, const char *b); bool iequals(const char *a, const char *b);
int icompare(const char *a, const char *b); int icompare(const char *a, const char *b);
...@@ -100,7 +100,7 @@ inline char tolower(int ch) ...@@ -100,7 +100,7 @@ inline char tolower(int ch)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string, std::string> splitTagName(const std::string &tag); std::tuple<std::string, std::string> splitTagName(std::string_view tag);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// generate a cif name, mainly used to generate asym_id's // generate a cif name, mainly used to generate asym_id's
......
...@@ -36,18 +36,19 @@ ...@@ -36,18 +36,19 @@
namespace cif namespace cif
{ {
struct ValidateCategory; struct ValidateCategory;
class ValidatorFactory;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class ValidationError : public std::exception class ValidationError : public std::exception
{ {
public: public:
ValidationError(const std::string& msg); ValidationError(const std::string &msg);
ValidationError(const std::string& cat, const std::string& item, ValidationError(const std::string &cat, const std::string &item,
const std::string& msg); const std::string &msg);
const char* what() const noexcept { return mMsg.c_str(); } const char *what() const noexcept { return mMsg.c_str(); }
std::string mMsg; std::string mMsg;
}; };
...@@ -55,58 +56,60 @@ class ValidationError : public std::exception ...@@ -55,58 +56,60 @@ class ValidationError : public std::exception
enum class DDL_PrimitiveType enum class DDL_PrimitiveType
{ {
Char, UChar, Numb Char,
UChar,
Numb
}; };
DDL_PrimitiveType mapToPrimitiveType(const std::string& s); DDL_PrimitiveType mapToPrimitiveType(std::string_view s);
struct ValidateType struct ValidateType
{ {
std::string mName; std::string mName;
DDL_PrimitiveType mPrimitiveType; DDL_PrimitiveType mPrimitiveType;
// std::regex mRx; // std::regex mRx;
boost::regex mRx; boost::regex mRx;
bool operator<(const ValidateType& rhs) const bool operator<(const ValidateType &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(mName, rhs.mName) < 0;
} }
// compare values based on type // compare values based on type
// int compare(const std::string& a, const std::string& b) const // int compare(const std::string& a, const std::string& b) const
// { // {
// return compare(a.c_str(), b.c_str()); // return compare(a.c_str(), b.c_str());
// } // }
int compare(const char* a, const char* b) const; int compare(const char *a, const char *b) const;
}; };
struct ValidateItem struct ValidateItem
{ {
std::string mTag; std::string mTag;
bool mMandatory; bool mMandatory;
const ValidateType* mType; const ValidateType *mType;
cif::iset mEnums; cif::iset mEnums;
std::string mDefault; std::string mDefault;
bool mDefaultIsNull; bool mDefaultIsNull;
ValidateCategory* mCategory = nullptr; ValidateCategory *mCategory = nullptr;
// ItemLinked is used for non-key links // ItemLinked is used for non-key links
struct ItemLinked struct ItemLinked
{ {
ValidateItem* mParent; ValidateItem *mParent;
std::string mParentItem; std::string mParentItem;
std::string mChildItem; std::string mChildItem;
}; };
std::vector<ItemLinked> mLinked; std::vector<ItemLinked> mLinked;
bool operator<(const ValidateItem& rhs) const bool operator<(const ValidateItem &rhs) const
{ {
return icompare(mTag, rhs.mTag) < 0; return icompare(mTag, rhs.mTag) < 0;
} }
bool operator==(const ValidateItem& rhs) const bool operator==(const ValidateItem &rhs) const
{ {
return iequals(mTag, rhs.mTag); return iequals(mTag, rhs.mTag);
} }
...@@ -116,22 +119,22 @@ struct ValidateItem ...@@ -116,22 +119,22 @@ struct ValidateItem
struct ValidateCategory struct ValidateCategory
{ {
std::string mName; std::string mName;
std::vector<std::string> mKeys; std::vector<std::string> mKeys;
cif::iset mGroups; cif::iset mGroups;
cif::iset mMandatoryFields; cif::iset mMandatoryFields;
std::set<ValidateItem> mItemValidators; std::set<ValidateItem> mItemValidators;
bool operator<(const ValidateCategory& rhs) const bool operator<(const ValidateCategory &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(mName, rhs.mName) < 0;
} }
void addItemValidator(ValidateItem&& v); void addItemValidator(ValidateItem &&v);
const ValidateItem* getValidatorForItem(std::string tag) const; const ValidateItem *getValidatorForItem(std::string_view tag) const;
const std::set<ValidateItem>& itemValidators() const const std::set<ValidateItem> &itemValidators() const
{ {
return mItemValidators; return mItemValidators;
} }
...@@ -139,12 +142,12 @@ struct ValidateCategory ...@@ -139,12 +142,12 @@ struct ValidateCategory
struct ValidateLink struct ValidateLink
{ {
int mLinkGroupID; int mLinkGroupID;
std::string mParentCategory; std::string mParentCategory;
std::vector<std::string> mParentKeys; std::vector<std::string> mParentKeys;
std::string mChildCategory; std::string mChildCategory;
std::vector<std::string> mChildKeys; std::vector<std::string> mChildKeys;
std::string mLinkGroupLabel; std::string mLinkGroupLabel;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -152,47 +155,72 @@ struct ValidateLink ...@@ -152,47 +155,72 @@ struct ValidateLink
class Validator class Validator
{ {
public: public:
friend class DictParser;
Validator(); Validator(std::string_view name, std::istream &is);
~Validator(); ~Validator();
Validator(const Validator& rhs) = delete; Validator(const Validator &rhs) = delete;
Validator& operator=(const Validator& rhs) = delete; Validator &operator=(const Validator &rhs) = delete;
Validator(Validator&& rhs);
Validator& operator=(Validator&& rhs);
void addTypeValidator(ValidateType&& v);
const ValidateType* getValidatorForType(std::string typeCode) const;
void addCategoryValidator(ValidateCategory&& v); Validator(Validator &&rhs);
const ValidateCategory* getValidatorForCategory(std::string category) const; Validator &operator=(Validator &&rhs);
void addLinkValidator(ValidateLink&& v); friend class DictParser;
std::vector<const ValidateLink*> getLinksForParent(const std::string& category) const; friend class ValidatorFactory;
std::vector<const ValidateLink*> getLinksForChild(const std::string& category) const;
void reportError(const std::string& msg, bool fatal); void addTypeValidator(ValidateType &&v);
const ValidateType *getValidatorForType(std::string_view typeCode) const;
std::string dictName() const { return mName; }
void dictName(const std::string& name) { mName = name; }
std::string dictVersion() const { return mVersion; } void addCategoryValidator(ValidateCategory &&v);
void dictVersion(const std::string& version) { mVersion = version; } const ValidateCategory *getValidatorForCategory(std::string_view category) const;
void addLinkValidator(ValidateLink &&v);
std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const;
std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const;
void reportError(const std::string &msg, bool fatal) const;
std::string dictName() const { return mName; }
void dictName(const std::string &name) { mName = name; }
std::string dictVersion() const { return mVersion; }
void dictVersion(const std::string &version) { mVersion = version; }
private: private:
// name is fully qualified here: // name is fully qualified here:
ValidateItem* getValidatorForItem(std::string name) const; ValidateItem *getValidatorForItem(std::string_view name) const;
std::string mName; std::string mName;
std::string mVersion; std::string mVersion;
bool mStrict = false; bool mStrict = false;
// std::set<uint32_t> mSubCategories; // std::set<uint32_t> mSubCategories;
std::set<ValidateType> mTypeValidators; std::set<ValidateType> mTypeValidators;
std::set<ValidateCategory> mCategoryValidators; std::set<ValidateCategory> mCategoryValidators;
std::vector<ValidateLink> mLinkValidators; std::vector<ValidateLink> mLinkValidators;
};
// --------------------------------------------------------------------
class ValidatorFactory
{
public:
static ValidatorFactory &instance()
{
return sInstance;
}
const Validator &operator[](std::string_view dictionary);
private:
static ValidatorFactory sInstance;
ValidatorFactory();
std::mutex mMutex;
std::list<Validator> mValidators;
}; };
} } // namespace cif
...@@ -104,6 +104,7 @@ class Compound ...@@ -104,6 +104,7 @@ class Compound
std::string id() const { return mID; } std::string id() const { return mID; }
std::string name() const { return mName; } std::string name() const { return mName; }
std::string type() const { return mType; } std::string type() const { return mType; }
std::string group() const { return mGroup; }
std::string formula() const { return mFormula; } std::string formula() const { return mFormula; }
float formulaWeight() const { return mFormulaWeight; } float formulaWeight() const { return mFormulaWeight; }
int formalCharge() const { return mFormalCharge; } int formalCharge() const { return mFormalCharge; }
...@@ -130,11 +131,12 @@ class Compound ...@@ -130,11 +131,12 @@ class Compound
friend class CCP4CompoundFactoryImpl; friend class CCP4CompoundFactoryImpl;
Compound(cif::Datablock &db); Compound(cif::Datablock &db);
Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type); Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type, const std::string &group);
std::string mID; std::string mID;
std::string mName; std::string mName;
std::string mType; std::string mType;
std::string mGroup;
std::string mFormula; std::string mFormula;
float mFormulaWeight = 0; float mFormulaWeight = 0;
int mFormalCharge = 0; int mFormalCharge = 0;
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright Maarten L. Hekkelman, Radboud University 2008-2011.
* Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// --------------------------------------------------------------------
// uBlas compatible matrix types
#pragma once
#include <iostream>
#include <vector>
// matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
// element m i,j is mapped to [i * n + j] and thus storage is row major
template <typename T>
class MatrixBase
{
public:
using value_type = T;
virtual ~MatrixBase() {}
virtual uint32_t dim_m() const = 0;
virtual uint32_t dim_n() const = 0;
virtual value_type &operator()(uint32_t i, uint32_t j) { throw std::runtime_error("unimplemented method"); }
virtual value_type operator()(uint32_t i, uint32_t j) const = 0;
MatrixBase &operator*=(const value_type &rhs);
MatrixBase &operator-=(const value_type &rhs);
};
template <typename T>
MatrixBase<T> &MatrixBase<T>::operator*=(const T &rhs)
{
for (uint32_t i = 0; i < dim_m(); ++i)
{
for (uint32_t j = 0; j < dim_n(); ++j)
{
operator()(i, j) *= rhs;
}
}
return *this;
}
template <typename T>
MatrixBase<T> &MatrixBase<T>::operator-=(const T &rhs)
{
for (uint32_t i = 0; i < dim_m(); ++i)
{
for (uint32_t j = 0; j < dim_n(); ++j)
{
operator()(i, j) -= rhs;
}
}
return *this;
}
template <typename T>
std::ostream &operator<<(std::ostream &lhs, const MatrixBase<T> &rhs)
{
lhs << '[' << rhs.dim_m() << ',' << rhs.dim_n() << ']' << '(';
for (uint32_t i = 0; i < rhs.dim_m(); ++i)
{
lhs << '(';
for (uint32_t j = 0; j < rhs.dim_n(); ++j)
{
if (j > 0)
lhs << ',';
lhs << rhs(i, j);
}
lhs << ')';
}
lhs << ')';
return lhs;
}
template <typename T>
class Matrix : public MatrixBase<T>
{
public:
using value_type = T;
template <typename T2>
Matrix(const MatrixBase<T2> &m)
: m_m(m.dim_m())
, m_n(m.dim_n())
{
m_data = new value_type[m_m * m_n];
for (uint32_t i = 0; i < m_m; ++i)
{
for (uint32_t j = 0; j < m_n; ++j)
operator()(i, j) = m(i, j);
}
}
Matrix()
: m_data(nullptr)
, m_m(0)
, m_n(0)
{
}
Matrix(const Matrix &m)
: m_m(m.m_m)
, m_n(m.m_n)
{
m_data = new value_type[m_m * m_n];
std::copy(m.m_data, m.m_data + (m_m * m_n), m_data);
}
Matrix &operator=(const Matrix &m)
{
value_type *t = new value_type[m.m_m * m.m_n];
std::copy(m.m_data, m.m_data + (m.m_m * m.m_n), t);
delete[] m_data;
m_data = t;
m_m = m.m_m;
m_n = m.m_n;
return *this;
}
Matrix(uint32_t m, uint32_t n, T v = T())
: m_m(m)
, m_n(n)
{
m_data = new value_type[m_m * m_n];
std::fill(m_data, m_data + (m_m * m_n), v);
}
virtual ~Matrix()
{
delete[] m_data;
}
virtual uint32_t dim_m() const { return m_m; }
virtual uint32_t dim_n() const { return m_n; }
virtual value_type operator()(uint32_t i, uint32_t j) const
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
virtual value_type &operator()(uint32_t i, uint32_t j)
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
template <typename Func>
void each(Func f)
{
for (uint32_t i = 0; i < m_m * m_n; ++i)
f(m_data[i]);
}
template <typename U>
Matrix &operator/=(U v)
{
for (uint32_t i = 0; i < m_m * m_n; ++i)
m_data[i] /= v;
return *this;
}
private:
value_type *m_data;
uint32_t m_m, m_n;
};
// --------------------------------------------------------------------
template <typename T>
class SymmetricMatrix : public MatrixBase<T>
{
public:
typedef typename MatrixBase<T>::value_type value_type;
SymmetricMatrix(uint32_t n, T v = T())
: m_owner(true)
, m_n(n)
{
uint32_t N = (m_n * (m_n + 1)) / 2;
m_data = new value_type[N];
std::fill(m_data, m_data + N, v);
}
SymmetricMatrix(const T *data, uint32_t n)
: m_owner(false)
, m_data(const_cast<T *>(data))
, m_n(n)
{
}
virtual ~SymmetricMatrix()
{
if (m_owner)
delete[] m_data;
}
virtual uint32_t dim_m() const { return m_n; }
virtual uint32_t dim_n() const { return m_n; }
T operator()(uint32_t i, uint32_t j) const;
virtual T &operator()(uint32_t i, uint32_t j);
// erase two rows, add one at the end (for neighbour joining)
void erase_2(uint32_t i, uint32_t j);
template <typename Func>
void each(Func f)
{
uint32_t N = (m_n * (m_n + 1)) / 2;
for (uint32_t i = 0; i < N; ++i)
f(m_data[i]);
}
template <typename U>
SymmetricMatrix &operator/=(U v)
{
uint32_t N = (m_n * (m_n + 1)) / 2;
for (uint32_t i = 0; i < N; ++i)
m_data[i] /= v;
return *this;
}
private:
bool m_owner;
value_type *m_data;
uint32_t m_n;
};
template <typename T>
inline T SymmetricMatrix<T>::operator()(uint32_t i, uint32_t j) const
{
return i < j
? m_data[(j * (j + 1)) / 2 + i]
: m_data[(i * (i + 1)) / 2 + j];
}
template <typename T>
inline T &SymmetricMatrix<T>::operator()(uint32_t i, uint32_t j)
{
if (i > j)
std::swap(i, j);
assert(j < m_n);
return m_data[(j * (j + 1)) / 2 + i];
}
template <typename T>
void SymmetricMatrix<T>::erase_2(uint32_t di, uint32_t dj)
{
uint32_t s = 0, d = 0;
for (uint32_t i = 0; i < m_n; ++i)
{
for (uint32_t j = 0; j < i; ++j)
{
if (i != di and j != dj and i != dj and j != di)
{
if (s != d)
m_data[d] = m_data[s];
++d;
}
++s;
}
}
--m_n;
}
template <typename T>
class IdentityMatrix : public MatrixBase<T>
{
public:
typedef typename MatrixBase<T>::value_type value_type;
IdentityMatrix(uint32_t n)
: m_n(n)
{
}
virtual uint32_t dim_m() const { return m_n; }
virtual uint32_t dim_n() const { return m_n; }
virtual value_type operator()(uint32_t i, uint32_t j) const
{
value_type result = 0;
if (i == j)
result = 1;
return result;
}
private:
uint32_t m_n;
};
// --------------------------------------------------------------------
// matrix functions
template <typename T>
Matrix<T> operator*(const MatrixBase<T> &lhs, const MatrixBase<T> &rhs)
{
Matrix<T> result(std::min(lhs.dim_m(), rhs.dim_m()), std::min(lhs.dim_n(), rhs.dim_n()));
for (uint32_t i = 0; i < result.dim_m(); ++i)
{
for (uint32_t j = 0; j < result.dim_n(); ++j)
{
for (uint32_t li = 0, rj = 0; li < lhs.dim_m() and rj < rhs.dim_n(); ++li, ++rj)
result(i, j) += lhs(li, j) * rhs(i, rj);
}
}
return result;
}
template <typename T>
Matrix<T> operator*(const MatrixBase<T> &lhs, T rhs)
{
Matrix<T> result(lhs);
result *= rhs;
return result;
}
template <typename T>
Matrix<T> operator-(const MatrixBase<T> &lhs, const MatrixBase<T> &rhs)
{
Matrix<T> result(std::min(lhs.dim_m(), rhs.dim_m()), std::min(lhs.dim_n(), rhs.dim_n()));
for (uint32_t i = 0; i < result.dim_m(); ++i)
{
for (uint32_t j = 0; j < result.dim_n(); ++j)
{
result(i, j) = lhs(i, j) - rhs(i, j);
}
}
return result;
}
template <typename T>
Matrix<T> operator-(const MatrixBase<T> &lhs, T rhs)
{
Matrix<T> result(lhs.dim_m(), lhs.dim_n());
result -= rhs;
return result;
}
// template <typename T>
// symmetric_matrix<T> hammingDistance(const MatrixBase<T> &lhs, T rhs);
// template <typename T>
// std::vector<T> sum(const MatrixBase<T> &m);
/*- /*-
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
* *
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this * 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer * list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
namespace mmcif namespace mmcif
{ {
typedef boost::math::quaternion<float> Quaternion; typedef boost::math::quaternion<float> Quaternion;
const double const double
kPI = 3.141592653589793238462643383279502884; kPI = 3.141592653589793238462643383279502884;
...@@ -51,26 +51,43 @@ const double ...@@ -51,26 +51,43 @@ const double
// float x, y, z; // float x, y, z;
// tie(x, y, z) = atom.loc(); // tie(x, y, z) = atom.loc();
template<typename F> template <typename F>
struct PointF struct PointF
{ {
typedef F FType; typedef F FType;
FType mX, mY, mZ; FType mX, mY, mZ;
PointF() : mX(0), mY(0), mZ(0) {}
PointF(FType x, FType y, FType z) : mX(x), mY(y), mZ(z) {}
template<typename PF> PointF()
PointF(const PointF<PF>& pt) : mX(0)
, mY(0)
, mZ(0)
{
}
PointF(FType x, FType y, FType z)
: mX(x)
, mY(y)
, mZ(z)
{
}
template <typename PF>
PointF(const PointF<PF> &pt)
: mX(static_cast<F>(pt.mX)) : mX(static_cast<F>(pt.mX))
, mY(static_cast<F>(pt.mY)) , mY(static_cast<F>(pt.mY))
, mZ(static_cast<F>(pt.mZ)) {} , mZ(static_cast<F>(pt.mZ))
{
}
#if HAVE_LIBCLIPPER #if HAVE_LIBCLIPPER
PointF(const clipper::Coord_orth& pt): mX(pt[0]), mY(pt[1]), mZ(pt[2]) {} PointF(const clipper::Coord_orth &pt)
: mX(pt[0])
, mY(pt[1])
, mZ(pt[2])
{
}
PointF& operator=(const clipper::Coord_orth& rhs) PointF &operator=(const clipper::Coord_orth &rhs)
{ {
mX = rhs[0]; mX = rhs[0];
mY = rhs[1]; mY = rhs[1];
...@@ -79,72 +96,72 @@ struct PointF ...@@ -79,72 +96,72 @@ struct PointF
} }
#endif #endif
template<typename PF> template <typename PF>
PointF& operator=(const PointF<PF>& rhs) PointF &operator=(const PointF<PF> &rhs)
{ {
mX = static_cast<F>(rhs.mX); mX = static_cast<F>(rhs.mX);
mY = static_cast<F>(rhs.mY); mY = static_cast<F>(rhs.mY);
mZ = static_cast<F>(rhs.mZ); mZ = static_cast<F>(rhs.mZ);
return *this; return *this;
} }
FType& getX() { return mX; } FType &getX() { return mX; }
FType getX() const { return mX; } FType getX() const { return mX; }
void setX(FType x) { mX = x; } void setX(FType x) { mX = x; }
FType& getY() { return mY; } FType &getY() { return mY; }
FType getY() const { return mY; } FType getY() const { return mY; }
void setY(FType y) { mY = y; } void setY(FType y) { mY = y; }
FType& getZ() { return mZ; } FType &getZ() { return mZ; }
FType getZ() const { return mZ; } FType getZ() const { return mZ; }
void setZ(FType z) { mZ = z; } void setZ(FType z) { mZ = z; }
PointF& operator+=(const PointF& rhs) PointF &operator+=(const PointF &rhs)
{ {
mX += rhs.mX; mX += rhs.mX;
mY += rhs.mY; mY += rhs.mY;
mZ += rhs.mZ; mZ += rhs.mZ;
return *this; return *this;
} }
PointF& operator+=(FType d) PointF &operator+=(FType d)
{ {
mX += d; mX += d;
mY += d; mY += d;
mZ += d; mZ += d;
return *this; return *this;
} }
PointF& operator-=(const PointF& rhs) PointF &operator-=(const PointF &rhs)
{ {
mX -= rhs.mX; mX -= rhs.mX;
mY -= rhs.mY; mY -= rhs.mY;
mZ -= rhs.mZ; mZ -= rhs.mZ;
return *this; return *this;
} }
PointF& operator-=(FType d) PointF &operator-=(FType d)
{ {
mX -= d; mX -= d;
mY -= d; mY -= d;
mZ -= d; mZ -= d;
return *this; return *this;
} }
PointF& operator*=(FType rhs) PointF &operator*=(FType rhs)
{ {
mX *= rhs; mX *= rhs;
mY *= rhs; mY *= rhs;
mZ *= rhs; mZ *= rhs;
return *this; return *this;
} }
PointF& operator/=(FType rhs) PointF &operator/=(FType rhs)
{ {
mX /= rhs; mX /= rhs;
mY /= rhs; mY /= rhs;
...@@ -162,18 +179,18 @@ struct PointF ...@@ -162,18 +179,18 @@ struct PointF
} }
return length; return length;
} }
void rotate(const boost::math::quaternion<FType>& q) void rotate(const boost::math::quaternion<FType> &q)
{ {
boost::math::quaternion<FType> p(0, mX, mY, mZ); boost::math::quaternion<FType> p(0, mX, mY, mZ);
p = q * p * boost::math::conj(q); p = q * p * boost::math::conj(q);
mX = p.R_component_2(); mX = p.R_component_2();
mY = p.R_component_3(); mY = p.R_component_3();
mZ = p.R_component_4(); mZ = p.R_component_4();
} }
#if HAVE_LIBCLIPPER #if HAVE_LIBCLIPPER
operator clipper::Coord_orth() const operator clipper::Coord_orth() const
{ {
...@@ -181,21 +198,21 @@ struct PointF ...@@ -181,21 +198,21 @@ struct PointF
} }
#endif #endif
operator std::tuple<const FType&, const FType&, const FType&>() const operator std::tuple<const FType &, const FType &, const FType &>() const
{ {
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ)); return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
} }
operator std::tuple<FType&,FType&,FType&>() operator std::tuple<FType &, FType &, FType &>()
{ {
return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ)); return std::make_tuple(std::ref(mX), std::ref(mY), std::ref(mZ));
} }
bool operator==(const PointF& rhs) const bool operator==(const PointF &rhs) const
{ {
return mX == rhs.mX and mY == rhs.mY and mZ == rhs.mZ; return mX == rhs.mX and mY == rhs.mY and mZ == rhs.mZ;
} }
// consider point as a vector... perhaps I should rename Point? // consider point as a vector... perhaps I should rename Point?
FType lengthsq() const FType lengthsq() const
{ {
...@@ -211,45 +228,45 @@ struct PointF ...@@ -211,45 +228,45 @@ struct PointF
typedef PointF<float> Point; typedef PointF<float> Point;
typedef PointF<double> DPoint; typedef PointF<double> DPoint;
template<typename F> template <typename F>
inline std::ostream& operator<<(std::ostream& os, const PointF<F>& pt) inline std::ostream &operator<<(std::ostream &os, const PointF<F> &pt)
{ {
os << '(' << pt.mX << ',' << pt.mY << ',' << pt.mZ << ')'; os << '(' << pt.mX << ',' << pt.mY << ',' << pt.mZ << ')';
return os; return os;
} }
template<typename F> template <typename F>
inline PointF<F> operator+(const PointF<F>& lhs, const PointF<F>& rhs) inline PointF<F> operator+(const PointF<F> &lhs, const PointF<F> &rhs)
{ {
return PointF<F>(lhs.mX + rhs.mX, lhs.mY + rhs.mY, lhs.mZ + rhs.mZ); return PointF<F>(lhs.mX + rhs.mX, lhs.mY + rhs.mY, lhs.mZ + rhs.mZ);
} }
template<typename F> template <typename F>
inline PointF<F> operator-(const PointF<F>& lhs, const PointF<F>& rhs) inline PointF<F> operator-(const PointF<F> &lhs, const PointF<F> &rhs)
{ {
return PointF<F>(lhs.mX - rhs.mX, lhs.mY - rhs.mY, lhs.mZ - rhs.mZ); return PointF<F>(lhs.mX - rhs.mX, lhs.mY - rhs.mY, lhs.mZ - rhs.mZ);
} }
template<typename F> template <typename F>
inline PointF<F> operator-(const PointF<F>& pt) inline PointF<F> operator-(const PointF<F> &pt)
{ {
return PointF<F>(-pt.mX, -pt.mY, -pt.mZ); return PointF<F>(-pt.mX, -pt.mY, -pt.mZ);
} }
template<typename F> template <typename F>
inline PointF<F> operator*(const PointF<F>& pt, F f) inline PointF<F> operator*(const PointF<F> &pt, F f)
{ {
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f); return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
} }
template<typename F> template <typename F>
inline PointF<F> operator*(F f, const PointF<F>& pt) inline PointF<F> operator*(F f, const PointF<F> &pt)
{ {
return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f); return PointF<F>(pt.mX * f, pt.mY * f, pt.mZ * f);
} }
template<typename F> template <typename F>
inline PointF<F> operator/(const PointF<F>& pt, F f) inline PointF<F> operator/(const PointF<F> &pt, F f)
{ {
return PointF<F>(pt.mX / f, pt.mY / f, pt.mZ / f); return PointF<F>(pt.mX / f, pt.mY / f, pt.mZ / f);
} }
...@@ -257,17 +274,16 @@ inline PointF<F> operator/(const PointF<F>& pt, F f) ...@@ -257,17 +274,16 @@ inline PointF<F> operator/(const PointF<F>& pt, F f)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// several standard 3d operations // several standard 3d operations
template<typename F> template <typename F>
inline double DistanceSquared(const PointF<F>& a, const PointF<F>& b) inline double DistanceSquared(const PointF<F> &a, const PointF<F> &b)
{ {
return return (a.mX - b.mX) * (a.mX - b.mX) +
(a.mX - b.mX) * (a.mX - b.mX) + (a.mY - b.mY) * (a.mY - b.mY) +
(a.mY - b.mY) * (a.mY - b.mY) + (a.mZ - b.mZ) * (a.mZ - b.mZ);
(a.mZ - b.mZ) * (a.mZ - b.mZ);
} }
template<typename F> template <typename F>
inline double Distance(const PointF<F>& a, const PointF<F>& b) inline double Distance(const PointF<F> &a, const PointF<F> &b)
{ {
return sqrt( return sqrt(
(a.mX - b.mX) * (a.mX - b.mX) + (a.mX - b.mX) * (a.mX - b.mX) +
...@@ -275,44 +291,44 @@ inline double Distance(const PointF<F>& a, const PointF<F>& b) ...@@ -275,44 +291,44 @@ inline double Distance(const PointF<F>& a, const PointF<F>& b)
(a.mZ - b.mZ) * (a.mZ - b.mZ)); (a.mZ - b.mZ) * (a.mZ - b.mZ));
} }
template<typename F> template <typename F>
inline F DotProduct(const PointF<F>& a, const PointF<F>& b) inline F DotProduct(const PointF<F> &a, const PointF<F> &b)
{ {
return a.mX * b.mX + a.mY * b.mY + a.mZ * b.mZ; return a.mX * b.mX + a.mY * b.mY + a.mZ * b.mZ;
} }
template<typename F> template <typename F>
inline PointF<F> CrossProduct(const PointF<F>& a, const PointF<F>& b) inline PointF<F> CrossProduct(const PointF<F> &a, const PointF<F> &b)
{ {
return PointF<F>(a.mY * b.mZ - b.mY * a.mZ, return PointF<F>(a.mY * b.mZ - b.mY * a.mZ,
a.mZ * b.mX - b.mZ * a.mX, a.mZ * b.mX - b.mZ * a.mX,
a.mX * b.mY - b.mX * a.mY); a.mX * b.mY - b.mX * a.mY);
} }
template<typename F> template <typename F>
double Angle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3) double Angle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3)
{ {
PointF<F> v1 = p1 - p2; PointF<F> v1 = p1 - p2;
PointF<F> v2 = p3 - p2; PointF<F> v2 = p3 - p2;
return std::acos(DotProduct(v1, v2) / (v1.length() * v2.length())) * 180 / kPI; return std::acos(DotProduct(v1, v2) / (v1.length() * v2.length())) * 180 / kPI;
} }
template<typename F> template <typename F>
double DihedralAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3, const PointF<F>& p4) double DihedralAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3, const PointF<F> &p4)
{ {
PointF<F> v12 = p1 - p2; // vector from p2 to p1 PointF<F> v12 = p1 - p2; // vector from p2 to p1
PointF<F> v43 = p4 - p3; // vector from p3 to p4 PointF<F> v43 = p4 - p3; // vector from p3 to p4
PointF<F> z = p2 - p3; // vector from p3 to p2 PointF<F> z = p2 - p3; // vector from p3 to p2
PointF<F> p = CrossProduct(z, v12); PointF<F> p = CrossProduct(z, v12);
PointF<F> x = CrossProduct(z, v43); PointF<F> x = CrossProduct(z, v43);
PointF<F> y = CrossProduct(z, x); PointF<F> y = CrossProduct(z, x);
double u = DotProduct(x, x); double u = DotProduct(x, x);
double v = DotProduct(y, y); double v = DotProduct(y, y);
double result = 360; double result = 360;
if (u > 0 and v > 0) if (u > 0 and v > 0)
{ {
...@@ -321,33 +337,33 @@ double DihedralAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& ...@@ -321,33 +337,33 @@ double DihedralAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>&
if (u != 0 or v != 0) if (u != 0 or v != 0)
result = atan2(v, u) * 180 / kPI; result = atan2(v, u) * 180 / kPI;
} }
return result; return result;
} }
template<typename F> template <typename F>
double CosinusAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p3, const PointF<F>& p4) double CosinusAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p3, const PointF<F> &p4)
{ {
PointF<F> v12 = p1 - p2; PointF<F> v12 = p1 - p2;
PointF<F> v34 = p3 - p4; PointF<F> v34 = p3 - p4;
double result = 0; double result = 0;
double x = DotProduct(v12, v12) * DotProduct(v34, v34); double x = DotProduct(v12, v12) * DotProduct(v34, v34);
if (x > 0) if (x > 0)
result = DotProduct(v12, v34) / sqrt(x); result = DotProduct(v12, v34) / sqrt(x);
return result; return result;
} }
template<typename F> template <typename F>
auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF<F> &p) auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF<F> &p)
{ {
auto line = l2 - l1; auto line = l2 - l1;
auto p_to_l1 = p - l1; auto p_to_l1 = p - l1;
auto p_to_l2 = p - l2; auto p_to_l2 = p - l2;
auto cross = CrossProduct(p_to_l1, p_to_l2); auto cross = CrossProduct(p_to_l1, p_to_l2);
return cross.length() / line.length(); return cross.length() / line.length();
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -355,7 +371,7 @@ auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF< ...@@ -355,7 +371,7 @@ auto DistancePointToLine(const PointF<F> &l1, const PointF<F> &l2, const PointF<
// a random direction with a distance randomly chosen from a normal // a random direction with a distance randomly chosen from a normal
// distribution with a stddev of offset. // distribution with a stddev of offset.
template<typename F> template <typename F>
PointF<F> Nudge(PointF<F> p, F offset); PointF<F> Nudge(PointF<F> p, F offset);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -363,66 +379,77 @@ PointF<F> Nudge(PointF<F> p, F offset); ...@@ -363,66 +379,77 @@ PointF<F> Nudge(PointF<F> p, F offset);
Quaternion Normalize(Quaternion q); Quaternion Normalize(Quaternion q);
std::tuple<double,Point> QuaternionToAngleAxis(Quaternion q); std::tuple<double, Point> QuaternionToAngleAxis(Quaternion q);
Point Centroid(std::vector<Point>& Points); Point Centroid(const std::vector<Point> &Points);
Point CenterPoints(std::vector<Point>& Points); Point CenterPoints(std::vector<Point> &Points);
Quaternion AlignPoints(const std::vector<Point>& a, const std::vector<Point>& b);
double RMSd(const std::vector<Point>& a, const std::vector<Point>& b); /// \brief Returns how the two sets of points \a a and \b b can be aligned
///
/// \param a The first set of points
/// \param b The second set of points
/// \result The quaternion which should be applied to the points in \a a to
/// obtain the best superposition.
Quaternion AlignPoints(const std::vector<Point> &a, const std::vector<Point> &b);
/// \brief The RMSd for the points in \a a and \a b
double RMSd(const std::vector<Point> &a, const std::vector<Point> &b);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Helper class to generate evenly divided Points on a sphere // Helper class to generate evenly divided Points on a sphere
// we use a fibonacci sphere to calculate even distribution of the dots // we use a fibonacci sphere to calculate even distribution of the dots
template<int N> template <int N>
class SphericalDots class SphericalDots
{ {
public: public:
enum { P = 2 * N + 1 }; enum
typedef typename std::array<Point,P> array_type; {
typedef typename array_type::const_iterator iterator; P = 2 * N + 1
};
typedef typename std::array<Point, P> array_type;
typedef typename array_type::const_iterator iterator;
static SphericalDots& instance() static SphericalDots &instance()
{ {
static SphericalDots sInstance; static SphericalDots sInstance;
return sInstance; return sInstance;
} }
size_t size() const { return mPoints.size(); }
const Point operator[](uint32_t inIx) const { return mPoints[inIx]; }
iterator begin() const { return mPoints.begin(); }
iterator end() const { return mPoints.end(); }
double weight() const { return mWeight; } size_t size() const { return mPoints.size(); }
const Point operator[](uint32_t inIx) const { return mPoints[inIx]; }
iterator begin() const { return mPoints.begin(); }
iterator end() const { return mPoints.end(); }
double weight() const { return mWeight; }
SphericalDots() SphericalDots()
{ {
const double const double
kGoldenRatio = (1 + std::sqrt(5.0)) / 2; kGoldenRatio = (1 + std::sqrt(5.0)) / 2;
mWeight = (4 * kPI) / P; mWeight = (4 * kPI) / P;
auto p = mPoints.begin(); auto p = mPoints.begin();
for (int32_t i = -N; i <= N; ++i) for (int32_t i = -N; i <= N; ++i)
{ {
double lat = std::asin((2.0 * i) / P); double lat = std::asin((2.0 * i) / P);
double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio; double lon = std::fmod(i, kGoldenRatio) * 2 * kPI / kGoldenRatio;
p->mX = sin(lon) * cos(lat); p->mX = sin(lon) * cos(lat);
p->mY = cos(lon) * cos(lat); p->mY = cos(lon) * cos(lat);
p->mZ = sin(lat); p->mZ = sin(lat);
++p; ++p;
} }
} }
private: private:
array_type mPoints;
array_type mPoints; double mWeight;
double mWeight;
}; };
typedef SphericalDots<50> SphericalDots_50; typedef SphericalDots<50> SphericalDots_50;
} } // namespace mmcif
...@@ -137,6 +137,22 @@ class DSSP ...@@ -137,6 +137,22 @@ class DSSP
public: public:
friend class iterator; friend class iterator;
ResidueInfo()
: mImpl(nullptr)
{
}
ResidueInfo(const ResidueInfo &rhs)
: mImpl(rhs.mImpl)
{
}
ResidueInfo& operator=(const ResidueInfo &rhs)
{
mImpl = rhs.mImpl;
return *this;
}
explicit operator bool() const { return not empty(); } explicit operator bool() const { return not empty(); }
bool empty() const { return mImpl == nullptr; } bool empty() const { return mImpl == nullptr; }
......
...@@ -109,12 +109,12 @@ class Atom ...@@ -109,12 +109,12 @@ class Atom
float occupancy() const; float occupancy() const;
template <typename T> template <typename T>
T property(const std::string &name) const; T property(const std::string_view name) const;
void property(const std::string &name, const std::string &value); void property(const std::string_view name, const std::string &value);
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
void property(const std::string &name, const T &value) void property(const std::string_view name, const T &value)
{ {
property(name, std::to_string(value)); property(name, std::to_string(value));
} }
...@@ -236,6 +236,8 @@ class Residue ...@@ -236,6 +236,8 @@ class Residue
Atom atomByID(const std::string &atomID) const; Atom atomByID(const std::string &atomID) const;
const std::string &compoundID() const { return mCompoundID; } const std::string &compoundID() const { return mCompoundID; }
void setCompoundID(const std::string &id) { mCompoundID = id; }
const std::string &asymID() const { return mAsymID; } const std::string &asymID() const { return mAsymID; }
int seqID() const { return mSeqID; } int seqID() const { return mSeqID; }
std::string entityID() const; std::string entityID() const;
...@@ -404,7 +406,7 @@ class File : public std::enable_shared_from_this<File> ...@@ -404,7 +406,7 @@ class File : public std::enable_shared_from_this<File>
File(const File &) = delete; File(const File &) = delete;
File &operator=(const File &) = delete; File &operator=(const File &) = delete;
cif::Datablock& createDatablock(const std::string &name); cif::Datablock& createDatablock(const std::string_view name);
void load(const std::filesystem::path &path); void load(const std::filesystem::path &path);
void save(const std::filesystem::path &path); void save(const std::filesystem::path &path);
...@@ -461,9 +463,24 @@ class Structure ...@@ -461,9 +463,24 @@ class Structure
Atom getAtomByLabel(const std::string &atomID, const std::string &asymID, Atom getAtomByLabel(const std::string &atomID, const std::string &asymID,
const std::string &compID, int seqID, const std::string &altID = ""); const std::string &compID, int seqID, const std::string &altID = "");
/// \brief Return the atom closest to point \a p
Atom getAtomByPosition(Point p) const;
/// \brief Return the atom closest to point \a p with atom type \a type in a residue of type \a res_type
Atom getAtomByPositionAndType(Point p, std::string_view type, std::string_view res_type) const;
/// \brief Get a residue, if \a seqID is zero, the non-polymers are searched /// \brief Get a residue, if \a seqID is zero, the non-polymers are searched
const Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID = 0) const; const Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID = 0) const;
/// \brief Get a residue, if \a seqID is zero, the non-polymers are searched
Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID = 0);
/// \brief Get a the single residue for an asym with id \a asymID
const Residue &getResidue(const std::string &asymID) const;
/// \brief Get a the single residue for an asym with id \a asymID
Residue &getResidue(const std::string &asymID);
// map between auth and label locations // map between auth and label locations
std::tuple<std::string, int, std::string> MapAuthToLabel(const std::string &asymID, std::tuple<std::string, int, std::string> MapAuthToLabel(const std::string &asymID,
...@@ -488,7 +505,7 @@ class Structure ...@@ -488,7 +505,7 @@ class Structure
void removeAtom(Atom &a); void removeAtom(Atom &a);
void swapAtoms(Atom &a1, Atom &a2); // swap the labels for these atoms void swapAtoms(Atom &a1, Atom &a2); // swap the labels for these atoms
void moveAtom(Atom &a, Point p); // move atom to a new location void moveAtom(Atom &a, Point p); // move atom to a new location
void changeResidue(const Residue &res, const std::string &newCompound, void changeResidue(Residue &res, const std::string &newCompound,
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms); const std::vector<std::tuple<std::string, std::string>> &remappedAtoms);
/// \brief Create a new non-polymer entity, returns new ID /// \brief Create a new non-polymer entity, returns new ID
...@@ -519,15 +536,16 @@ class Structure ...@@ -519,15 +536,16 @@ class Structure
void cleanupEmptyCategories(); void cleanupEmptyCategories();
/// \brief Direct access to underlying data
cif::Category &category(std::string_view name) const;
cif::Datablock &datablock() const;
private: private:
friend Polymer; friend Polymer;
friend Residue; friend Residue;
// friend residue_view; // friend residue_view;
// friend residue_iterator; // friend residue_iterator;
cif::Category &category(const char *name) const;
cif::Datablock &datablock() const;
std::string insertCompound(const std::string &compoundID, bool isEntity); std::string insertCompound(const std::string &compoundID, bool isEntity);
void loadData(); void loadData();
......
...@@ -37,6 +37,11 @@ namespace mmcif ...@@ -37,6 +37,11 @@ namespace mmcif
// -------------------------------------------------------------------- // --------------------------------------------------------------------
enum class SpacegroupName
{
full, xHM, Hall
};
struct Spacegroup struct Spacegroup
{ {
const char* name; const char* name;
...@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize; ...@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code, using SpacegroupName::full
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type); // alternative for clipper's parsing code
} }
...@@ -175,860 +175,432 @@ struct SFDataArrayElement ...@@ -175,860 +175,432 @@ struct SFDataArrayElement
}; };
SFDataArrayElement kWKSFData[] = { SFDataArrayElement kWKSFData[] = {
{ H, 0, {{ 0.413048, 0.294953, 0.187491, 0.080701, 0.023736, 0.000049},
//{ H, 0, {{ 0.493002, 0.322912, 0.140191, 0.040810, 0.003038 }, { 15.569946, 32.398468, 5.711404, 61.889874, 1.334118, 0.000000}}},
// { 10.510900, 26.125700, 3.142360, 57.799698, 0.000000 }}}, { He, 0, {{ 0.732354, 0.753896, 0.283819, 0.190003, 0.039139, 0.000487},
////{ D, 0, {{ 0.493002, 0.322912, 0.140191, 0.040810, 0.003038 }, { 11.553918, 4.595831, 1.546299, 26.463964, 0.377523, 0.000000}}},
//// { 10.510900, 26.125700, 3.142360, 57.799698, 0.000000 }}}, { Li, 0, {{ 0.974637, 0.158472, 0.811855, 0.262416, 0.790108, 0.002542},
//{ H, -1, {{ 0.897661, 0.565616, 0.415815, 0.116973, 0.002389 }, { 4.334946, 0.342451, 97.102966,201.363831, 1.409234, 0.000000}}},
// { 53.136799, 15.187000, 186.575989, 3.567090, 0.000000 }}}, { Be, 0, {{ 1.533712, 0.638283, 0.601052, 0.106139, 1.118414, 0.002511},
//{ He, 0, {{ 0.873400, 0.630900, 0.311200, 0.178000, 0.006400 }, { 42.662079, 0.595420, 99.106499, 0.151340, 1.843093, 0.000000}}},
// { 9.103700, 3.356800, 22.927601, 0.982100, 0.000000 }}}, { B, 0, {{ 2.085185, 1.064580, 1.062788, 0.140515, 0.641784, 0.003823},
//{ Li, 0, {{ 1.128200, 0.750800, 0.617500, 0.465300, 0.037700 }, { 23.494068, 1.137894, 61.238976, 0.114886, 0.399036, 0.000000}}},
// { 3.954600, 1.052400, 85.390503, 168.261002, 0.000000 }}}, { C, 0, {{ 2.657506, 1.078079, 1.490909, -4.241070, 0.713791, 4.297983},
//{ Li, +1, {{ 0.696800, 0.788800, 0.341400, 0.156300, 0.016700 }, { 14.780758, 0.776775, 42.086842, -0.000294, 0.239535, 0.000000}}},
// { 4.623700, 1.955700, 0.631600, 10.095300, 0.000000 }}}, { N, 0, {{ 11.893780, 3.277479, 1.858092, 0.858927, 0.912985,-11.804902},
//{ Be, 0, {{ 1.591900, 1.127800, 0.539100, 0.702900, 0.038500 }, { 0.000158, 10.232723, 30.344690, 0.656065, 0.217287, 0.000000}}},
// { 43.642700, 1.862300, 103.483002, 0.542000, 0.000000 }}}, { O, 0, {{ 2.960427, 2.508818, 0.637853, 0.722838, 1.142756, 0.027014},
//{ Be, +2, {{ 6.260300, 0.884900, 0.799300, 0.164700, -6.109200 }, { 14.182259, 5.936858, 0.112726, 34.958481, 0.390240, 0.000000}}},
// { 0.002700, 0.831300, 2.275800, 5.114600, 0.000000 }}}, { F, 0, {{ 3.511943, 2.772244, 0.678385, 0.915159, 1.089261, 0.032557},
//{ B, 0, {{ 2.054500, 1.332600, 1.097900, 0.706800, -0.193200 }, { 10.687859, 4.380466, 0.093982, 27.255203, 0.313066, 0.000000}}},
// { 23.218500, 1.021000, 60.349800, 0.140300, 0.000000 }}}, { Ne, 0, {{ 4.183749, 2.905726, 0.520513, 1.135641, 1.228065, 0.025576},
//{ C, 0, {{ 2.310000, 1.020000, 1.588600, 0.865000, 0.215600 }, { 8.175457, 3.252536, 0.063295, 21.813910, 0.224952, 0.000000}}},
// { 20.843899, 10.207500, 0.568700, 51.651199, 0.000000 }}}, { Na, 0, {{ 4.910127, 3.081783, 1.262067, 1.098938, 0.560991, 0.079712},
//{ C, AtomTypeTraits::kWKSFVal, { 3.281434, 9.119178, 0.102763,132.013947, 0.405878, 0.000000}}},
// {{ 2.260690, 1.561650, 1.050750, 0.839259, 0.286977 }, { Mg, 0, {{ 4.708971, 1.194814, 1.558157, 1.170413, 3.239403, 0.126842},
// { 22.690701, 0.656665, 9.756180, 55.594898, 0.000000 }}}, { 4.875207,108.506081, 0.111516, 48.292408, 1.928171, 0.000000}}},
//{ N, 0, {{ 12.212600, 3.132200, 2.012500, 1.166300, -11.528999 }, { Al, 0, {{ 4.730796, 2.313951, 1.541980, 1.117564, 3.154754, 0.139509},
// { 0.005700, 9.893300, 28.997499, 0.582600, 0.000000 }}}, { 3.628931, 43.051167, 0.095960,108.932388, 1.555918, 0.000000}}},
//{ O, 0, {{ 3.048500, 2.286800, 1.546300, 0.867000, 0.250800 }, { Si, 0, {{ 5.275329, 3.191038, 1.511514, 1.356849, 2.519114, 0.145073},
// { 13.277100, 5.701100, 0.323900, 32.908897, 0.000000 }}}, { 2.631338, 33.730728, 0.081119, 86.288643, 1.170087, 0.000000}}},
//{ O, -1, {{ 4.191600, 1.639690, 1.526730, -20.306999, 21.941200 }, { P, 0, {{ 1.950541, 4.146930, 1.494560, 1.522042, 5.729711, 0.155233},
// { 12.857300, 4.172360, 47.017899, -0.014040, 0.000000 }}}, { 0.908139, 27.044952, 0.071280, 67.520187, 1.981173, 0.000000}}},
//{ F, 0, {{ 3.539200, 2.641200, 1.517000, 1.024300, 0.277600 }, { S, 0, {{ 6.372157, 5.154568, 1.473732, 1.635073, 1.209372, 0.154722},
// { 10.282499, 4.294400, 0.261500, 26.147600, 0.000000 }}}, { 1.514347, 22.092527, 0.061373, 55.445175, 0.646925, 0.000000}}},
//{ F, -1, {{ 3.632200, 3.510570, 1.260640, 0.940706, 0.653396 }, { Cl, 0, {{ 1.446071, 6.870609, 6.151801, 1.750347, 0.634168, 0.146773},
// { 5.277560, 14.735300, 0.442258, 47.343700, 0.000000 }}}, { 0.052357, 1.193165, 18.343416, 46.398396, 0.401005, 0.000000}}},
//{ Ne, 0, {{ 3.955300, 3.112500, 1.454600, 1.125100, 0.351500 }, { Ar, 0, {{ 7.188004, 6.638454, 0.454180, 1.929593, 1.523654, 0.265954},
// { 8.404200, 3.426200, 0.230600, 21.718399, 0.000000 }}}, { 0.956221, 15.339877, 15.339862, 39.043823, 0.062409, 0.000000}}},
//{ Na, 0, {{ 4.762600, 3.173600, 1.267400, 1.112800, 0.676000 }, { K, 0, {{ 8.163991, 7.146945, 1.070140, 0.877316, 1.486434, 0.253614},
// { 3.285000, 8.842199, 0.313600, 129.423996, 0.000000 }}}, { 12.816323, 0.808945,210.327011, 39.597652, 0.052821, 0.000000}}},
//{ Na, +1, {{ 3.256500, 3.936200, 1.399800, 1.003200, 0.404000 }, { Ca, 0, {{ 8.593655, 1.477324, 1.436254, 1.182839, 7.113258, 0.196255},
// { 2.667100, 6.115300, 0.200100, 14.039000, 0.000000 }}}, { 10.460644, 0.041891, 81.390381,169.847839, 0.688098, 0.000000}}},
//{ Mg, 0, {{ 5.420400, 2.173500, 1.226900, 2.307300, 0.858400 }, { Sc, 0, {{ 1.476566, 1.487278, 1.600187, 9.177463, 7.099750, 0.157765},
// { 2.827500, 79.261101, 0.380800, 7.193700, 0.000000 }}}, { 53.131023, 0.035325,137.319489, 9.098031, 0.602102, 0.000000}}},
//{ Mg, +2, {{ 3.498800, 3.837800, 1.328400, 0.849700, 0.485300 }, { Ti, 0, {{ 9.818524, 1.522646, 1.703101, 1.768774, 7.082555, 0.102473},
// { 2.167600, 4.754200, 0.185000, 10.141100, 0.000000 }}}, { 8.001879, 0.029763, 39.885422,120.157997, 0.532405, 0.000000}}},
//{ Al, 0, {{ 6.420200, 1.900200, 1.593600, 1.964600, 1.115100 }, { V, 0, {{ 10.473575, 1.547881, 1.986381, 1.865616, 7.056250, 0.067744},
// { 3.038700, 0.742600, 31.547199, 85.088600, 0.000000 }}}, { 7.081940, 0.026040, 31.909672,108.022842, 0.474882, 0.000000}}},
//{ Al, +3, {{ 4.174480, 3.387600, 1.202960, 0.528137, 0.706786 }, { Cr, 0, {{ 11.007069, 1.555477, 2.985293, 1.347855, 7.034779, 0.065510},
// { 1.938160, 4.145530, 0.228753, 8.285240, 0.000000 }}}, { 6.366281, 0.023987, 23.244839,105.774498, 0.429369, 0.000000}}},
//{ Si, 0, {{ 6.291500, 3.035300, 1.989100, 1.541000, 1.140700 }, { Mn, 0, {{ 11.709542, 1.733414, 2.673141, 2.023368, 7.003180, -0.147293},
// { 2.438600, 32.333698, 0.678500, 81.693695, 0.000000 }}}, { 5.597120, 0.017800, 21.788420, 89.517914, 0.383054, 0.000000}}},
//{ Si, AtomTypeTraits::kWKSFVal, { Fe, 0, {{ 12.311098, 1.876623, 3.066177, 2.070451, 6.975185, -0.304931},
// {{ 5.662690, 3.071640, 2.624460, 1.393200, 1.247070 }, { 5.009415, 0.014461, 18.743040, 82.767876, 0.346506, 0.000000}}},
// { 2.665200, 38.663399, 0.916946, 93.545799, 0.000000 }}}, { Co, 0, {{ 12.914510, 2.481908, 3.466894, 2.106351, 6.960892, -0.936572},
//{ Si, +4, {{ 4.439180, 3.203450, 1.194530, 0.416530, 0.746297 }, { 4.507138, 0.009126, 16.438129, 76.987320, 0.314418, 0.000000}}},
// { 1.641670, 3.437570, 0.214900, 6.653650, 0.000000 }}}, { Ni, 0, {{ 13.521865, 6.947285, 3.866028, 2.135900, 4.284731, -2.762697},
//{ P, 0, {{ 6.434500, 4.179100, 1.780000, 1.490800, 1.114900 }, { 4.077277, 0.286763, 14.622634, 71.966080, 0.004437, 0.000000}}},
// { 1.906700, 27.157000, 0.526000, 68.164497, 0.000000 }}}, { Cu, 0, {{ 14.014192, 4.784577, 5.056806, 1.457971, 6.932996, -3.254477},
//{ S, 0, {{ 6.905300, 5.203400, 1.437900, 1.586300, 0.866900 }, { 3.738280, 0.003744, 13.034982, 72.554794, 0.265666, 0.000000}}},
// { 1.467900, 22.215099, 0.253600, 56.172001, 0.000000 }}}, { Zn, 0, {{ 14.741002, 6.907748, 4.642337, 2.191766, 38.424042,-36.915829},
//{ Cl, 0, {{ 11.460400, 7.196400, 6.255600, 1.645500, -9.557400 }, { 3.388232, 0.243315, 11.903689, 63.312130, 0.000397, 0.000000}}},
// { 0.010400, 1.166200, 18.519400, 47.778400, 0.000000 }}}, { Ga, 0, {{ 15.758946, 6.841123, 4.121016, 2.714681, 2.395246, -0.847395},
//{ Cl, -1, {{ 18.291500, 7.208400, 6.533700, 2.338600, -16.378000 }, { 3.121754, 0.226057, 12.482196, 66.203621, 0.007238, 0.000000}}},
// { 0.006600, 1.171700, 19.542400, 60.448601, 0.000000 }}}, { Ge, 0, {{ 16.540613, 1.567900, 3.727829, 3.345098, 6.785079, 0.018726},
//{ Ar, 0, {{ 7.484500, 6.772300, 0.653900, 1.644200, 1.444500 }, { 2.866618, 0.012198, 13.432163, 58.866047, 0.210974, 0.000000}}},
// { 0.907200, 14.840700, 43.898300, 33.392899, 0.000000 }}}, { As, 0, {{ 17.025642, 4.503441, 3.715904, 3.937200, 6.790175, -2.984117},
//{ K, 0, {{ 8.218599, 7.439800, 1.051900, 0.865900, 1.422800 }, { 2.597739, 0.003012, 14.272119, 50.437996, 0.193015, 0.000000}}},
// { 12.794900, 0.774800, 213.186996, 41.684097, 0.000000 }}}, { Se, 0, {{ 17.354071, 4.653248, 4.259489, 4.136455, 6.749163, -3.160982},
//{ K, +1, {{ 7.957800, 7.491700, 6.359000, 1.191500, -4.997800 }, { 2.349787, 0.002550, 15.579460, 45.181202, 0.177432, 0.000000}}},
// { 12.633100, 0.767400, -0.002000, 31.912800, 0.000000 }}}, { Br, 0, {{ 17.550570, 5.411882, 3.937180, 3.880645, 6.707793, -2.492088},
//{ Ca, 0, {{ 8.626600, 7.387300, 1.589900, 1.021100, 1.375100 }, { 2.119226, 16.557184, 0.002481, 42.164009, 0.162121, 0.000000}}},
// { 10.442100, 0.659900, 85.748398, 178.436996, 0.000000 }}}, { Kr, 0, {{ 17.655279, 6.848105, 4.171004, 3.446760, 6.685200, -2.810592},
//{ Ca, +2, {{ 15.634800, 7.951800, 8.437200, 0.853700, -14.875000 }, { 1.908231, 16.606236, 0.001598, 39.917473, 0.146896, 0.000000}}},
// { -0.007400, 0.608900, 10.311600, 25.990499, 0.000000 }}}, { Rb, 0, {{ 8.123134, 2.138042, 6.761702, 1.156051, 17.679546, 1.139548},
//{ Sc, 0, {{ 9.189000, 7.367900, 1.640900, 1.468000, 1.332900 }, { 15.142385, 33.542667, 0.129372,224.132507, 1.713368, 0.000000}}},
// { 9.021299, 0.572900, 136.108002, 51.353100, 0.000000 }}}, { Sr, 0, {{ 17.730219, 9.795867, 6.099763, 2.620025, 0.600053, 1.140251},
//{ Sc, +3, {{ 13.400800, 8.027300, 1.659430, 1.579360, -6.666700 }, { 1.563060, 14.310868, 0.120574,135.771317, 0.120574, 0.000000}}},
// { 0.298540, 7.962900, -0.286040, 16.066200, 0.000000 }}}, { Y, 0, {{ 17.792040, 10.253252, 5.714949, 3.170516, 0.918251, 1.131787},
//{ Ti, 0, {{ 9.759500, 7.355800, 1.699100, 1.902100, 1.280700 }, { 1.429691, 13.132816, 0.112173,108.197029, 0.112173, 0.000000}}},
// { 7.850800, 0.500000, 35.633801, 116.104996, 0.000000 }}}, { Zr, 0, {{ 17.859772, 10.911038, 5.821115, 3.512513, 0.746965, 1.124859},
//{ Ti, +2, {{ 9.114230, 7.621740, 2.279300, 0.087899, 0.897155 }, { 1.310692, 12.319285, 0.104353, 91.777542, 0.104353, 0.000000}}},
// { 7.524300, 0.457585, 19.536100, 61.655800, 0.000000 }}}, { Nb, 0, {{ 17.958399, 12.063054, 5.007015, 3.287667, 1.531019, 1.123452},
//{ Ti, +3, {{ 17.734400, 8.738160, 5.256910, 1.921340, -14.652000 }, { 1.211590, 12.246687, 0.098615, 75.011948, 0.098615, 0.000000}}},
// { 0.220610, 7.047160, -0.157620, 15.976800, 0.000000 }}}, { Mo, 0, {{ 6.236218, 17.987711, 12.973127, 3.451426, 0.210899, 1.108770},
//{ Ti, +4, {{ 19.511400, 8.234730, 2.013410, 1.520800, -13.280000 }, { 0.090780, 1.108310, 11.468720, 66.684151, 0.090780, 0.000000}}},
// { 0.178847, 6.670180, -0.292630, 12.946400, 0.000000 }}}, { Tc, 0, {{ 17.840963, 3.428236, 1.373012, 12.947364, 6.335469, 1.074784},
//{ V, 0, {{ 10.297100, 7.351100, 2.070300, 2.057100, 1.219900 }, { 1.005729, 41.901382,119.320541, 9.781542, 0.083391, 0.000000}}},
// { 6.865700, 0.438500, 26.893799, 102.477997, 0.000000 }}}, { Ru, 0, {{ 6.271624, 17.906738, 14.123269, 3.746008, 0.908235, 1.043992},
//{ V, +2, {{ 10.106000, 7.354100, 2.288400, 0.022300, 1.229800 }, { 0.077040, 0.928222, 9.555345, 35.860680,123.552246, 0.000000}}},
// { 6.881800, 0.440900, 20.300400, 115.122002, 0.000000 }}}, { Rh, 0, {{ 6.216648, 17.919739, 3.854252, 0.840326, 15.173498, 0.995452},
//{ V, +3, {{ 9.431410, 7.741900, 2.153430, 0.016865, 0.656565 }, { 0.070789, 0.856121, 33.889484,121.686691, 9.029517, 0.000000}}},
// { 6.395350, 0.383349, 15.190800, 63.969002, 0.000000 }}}, { Pd, 0, {{ 6.121511, 4.784063, 16.631683, 4.318258, 13.246773, 0.883099},
//{ V, +5, {{ 15.688700, 8.142080, 2.030810, -9.576000, 1.714300 }, { 0.062549, 0.784031, 8.751391, 34.489983, 0.784031, 0.000000}}},
// { 0.679003, 5.401350, 9.972780, 0.940464, 0.000000 }}}, { Ag, 0, {{ 6.073874, 17.155437, 4.173344, 0.852238, 17.988686, 0.756603},
//{ Cr, 0, {{ 10.640600, 7.353700, 3.324000, 1.492200, 1.183200 }, { 0.055333, 7.896512, 28.443739,110.376106, 0.716809, 0.000000}}},
// { 6.103800, 0.392000, 20.262600, 98.739899, 0.000000 }}}, { Cd, 0, {{ 6.080986, 18.019468, 4.018197, 1.303510, 17.974669, 0.603504},
//{ Cr, +2, {{ 9.540340, 7.750900, 3.582740, 0.509107, 0.616898 }, { 0.048990, 7.273646, 29.119284, 95.831207, 0.661231, 0.000000}}},
// { 5.660780, 0.344261, 13.307500, 32.422401, 0.000000 }}}, { In, 0, {{ 6.196477, 18.816183, 4.050479, 1.638929, 17.962912, 0.333097},
//{ Cr, +3, {{ 9.680900, 7.811360, 2.876030, 0.113575, 0.518275 }, { 0.042072, 6.695665, 31.009790,103.284348, 0.610714, 0.000000}}},
// { 5.594630, 0.334393, 12.828800, 32.876099, 0.000000 }}}, { Sn, 0, {{ 19.325171, 6.281571, 4.498866, 1.856934, 17.917318, 0.119024},
//{ Mn, 0, {{ 11.281900, 7.357300, 3.019300, 2.244100, 1.089600 }, { 6.118104, 0.036915, 32.529045, 95.037186, 0.565651, 0.000000}}},
// { 5.340900, 0.343200, 17.867399, 83.754303, 0.000000 }}}, { Sb, 0, {{ 5.394956, 6.549570, 19.650681, 1.827820, 17.867832, -0.290506},
//{ Mn, +2, {{ 10.806100, 7.362000, 3.526800, 0.218400, 1.087400 }, { 33.326523, 0.030974, 5.564929, 87.130966, 0.523992, 0.000000}}},
// { 5.279600, 0.343500, 14.343000, 41.323502, 0.000000 }}}, { Te, 0, {{ 6.660302, 6.940756, 19.847015, 1.557175, 17.802427, -0.806668},
//{ Mn, +3, {{ 9.845210, 7.871940, 3.565310, 0.323613, 0.393974 }, { 33.031654, 0.025750, 5.065547, 84.101616, 0.487660, 0.000000}}},
// { 4.917970, 0.294393, 10.817100, 24.128099, 0.000000 }}}, { I, 0, {{ 19.884502, 6.736593, 8.110516, 1.170953, 17.548716, -0.448811},
//{ Mn, +4, {{ 9.962530, 7.970570, 2.760670, 0.054447, 0.251877 }, { 4.628591, 0.027754, 31.849096, 84.406387, 0.463550, 0.000000}}},
// { 4.848500, 0.283303, 10.485200, 27.573000, 0.000000 }}}, { Xe, 0, {{ 19.978920, 11.774945, 9.332182, 1.244749, 17.737501, -6.065902},
//{ Fe, 0, {{ 11.769500, 7.357300, 3.522200, 2.304500, 1.036900 }, { 4.143356, 0.010142, 28.796200, 75.280685, 0.413616, 0.000000}}},
// { 4.761100, 0.307200, 15.353500, 76.880501, 0.000000 }}}, { Cs, 0, {{ 17.418674, 8.314444, 10.323193, 1.383834, 19.876251, -2.322802},
//{ Fe, +2, {{ 11.042400, 7.374000, 4.134600, 0.439900, 1.009700 }, { 0.399828, 0.016872, 25.605827,233.339676, 3.826915, 0.000000}}},
// { 4.653800, 0.305300, 12.054600, 31.280899, 0.000000 }}}, { Ba, 0, {{ 19.747343, 17.368477, 10.465718, 2.592602, 11.003653, -5.183497},
//{ Fe, +3, {{ 11.176400, 7.386300, 3.394800, 0.072400, 0.970700 }, { 3.481823, 0.371224, 21.226641,173.834274, 0.010719, 0.000000}}},
// { 4.614700, 0.300500, 11.672900, 38.556599, 0.000000 }}}, { La, 0, {{ 19.966019, 27.329655, 11.018425, 3.086696, 17.335455,-21.745489},
//{ Co, 0, {{ 12.284100, 7.340900, 4.003400, 2.348800, 1.011800 }, { 3.197408, 0.003446, 19.955492,141.381973, 0.341817, 0.000000}}},
// { 4.279100, 0.278400, 13.535900, 71.169197, 0.000000 }}}, { Ce, 0, {{ 17.355122, 43.988499, 20.546650, 3.130670, 11.353665,-38.386017},
//{ Co, +2, {{ 11.229600, 7.388300, 4.739300, 0.710800, 0.932400 }, { 0.328369, 0.002047, 3.088196,134.907654, 18.832960, 0.000000}}},
// { 4.123100, 0.272600, 10.244300, 25.646599, 0.000000 }}}, { Pr, 0, {{ 21.551311, 17.161730, 11.903859, 2.679103, 9.564197, -3.871068},
//{ Co, +3, {{ 10.337999, 7.881730, 4.767950, 0.725591, 0.286667 }, { 2.995675, 0.312491, 17.716705,152.192825, 0.010468, 0.000000}}},
// { 3.909690, 0.238668, 8.355830, 18.349100, 0.000000 }}}, { Nd, 0, {{ 17.331244, 62.783924, 12.160097, 2.663483, 22.239950,-57.189842},
//{ Ni, 0, {{ 12.837600, 7.292000, 4.443800, 2.380000, 1.034100 }, { 0.300269, 0.001320, 17.026001,148.748993, 2.910268, 0.000000}}},
// { 3.878500, 0.256500, 12.176300, 66.342102, 0.000000 }}}, { Pm, 0, {{ 17.286388, 51.560162, 12.478557, 2.675515, 22.960947,-45.973682},
//{ Ni, +2, {{ 11.416600, 7.400500, 5.344200, 0.977300, 0.861400 }, { 0.286620, 0.001550, 16.223755,143.984512, 2.796480, 0.000000}}},
// { 3.676600, 0.244900, 8.873000, 22.162600, 0.000000 }}}, { Sm, 0, {{ 23.700363, 23.072214, 12.777782, 2.684217, 17.204367,-17.452166},
//{ Ni, +3, {{ 10.780600, 7.758680, 5.227460, 0.847114, 0.386044 }, { 2.689539, 0.003491, 15.495437,139.862473, 0.274536, 0.000000}}},
// { 3.547700, 0.223140, 7.644680, 16.967300, 0.000000 }}}, { Eu, 0, {{ 17.186195, 37.156837, 13.103387, 2.707246, 24.419271,-31.586687},
//{ Cu, 0, {{ 13.337999, 7.167600, 5.615800, 1.673500, 1.191000 }, { 0.261678, 0.001995, 14.787360,134.816299, 2.581883, 0.000000}}},
// { 3.582800, 0.247000, 11.396600, 64.812599, 0.000000 }}}, { Gd, 0, {{ 24.898117, 17.104952, 13.222581, 3.266152, 48.995213,-43.505684},
//{ Cu, +1, {{ 11.947500, 7.357300, 6.245500, 1.557800, 0.890000 }, { 2.435028, 0.246961, 13.996325,110.863091, 0.001383, 0.000000}}},
// { 3.366900, 0.227400, 8.662500, 25.848700, 0.000000 }}}, { Tb, 0, {{ 25.910013, 32.344139, 13.765117, 2.751404, 17.064405,-26.851971},
//{ Cu, +2, {{ 11.816800, 7.111810, 5.781350, 1.145230, 1.144310 }, { 2.373912, 0.002034, 13.481969,125.836510, 0.236916, 0.000000}}},
// { 3.374840, 0.244078, 7.987600, 19.896999, 0.000000 }}}, { Dy, 0, {{ 26.671785, 88.687576, 14.065445, 2.768497, 17.067781,-83.279831},
//{ Zn, 0, {{ 14.074300, 7.031800, 5.162500, 2.410000, 1.304100 }, { 2.282593, 0.000665, 12.920230,121.937187, 0.225531, 0.000000}}},
// { 3.265500, 0.233300, 10.316299, 58.709702, 0.000000 }}}, { Ho, 0, {{ 27.150190, 16.999819, 14.059334, 3.386979, 46.546471,-41.165253},
//{ Zn, +2, {{ 11.971900, 7.386200, 6.466800, 1.394000, 0.780700 }, { 2.169660, 0.215414, 12.213148,100.506783, 0.001211, 0.000000}}},
// { 2.994600, 0.203100, 7.082600, 18.099499, 0.000000 }}}, { Er, 0, {{ 28.174887, 82.493271, 14.624002, 2.802756, 17.018515,-77.135223},
//{ Ga, 0, {{ 15.235400, 6.700600, 4.359100, 2.962300, 1.718900 }, { 2.120995, 0.000640, 11.915256,114.529938, 0.207519, 0.000000}}},
// { 3.066900, 0.241200, 10.780500, 61.413498, 0.000000 }}}, { Tm, 0, {{ 28.925894, 76.173798, 14.904704, 2.814812, 16.998117,-70.839813},
//{ Ga, +3, {{ 12.691999, 6.698830, 6.066920, 1.006600, 1.535450 }, { 2.046203, 0.000656, 11.465375,111.411980, 0.199376, 0.000000}}},
// { 2.812620, 0.227890, 6.364410, 14.412200, 0.000000 }}}, { Yb, 0, {{ 29.676760, 65.624069, 15.160854, 2.830288, 16.997850,-60.313812},
//{ Ge, 0, {{ 16.081600, 6.374700, 3.706800, 3.683000, 2.131300 }, { 1.977630, 0.000720, 11.044622,108.139153, 0.192110, 0.000000}}},
// { 2.850900, 0.251600, 11.446800, 54.762501, 0.000000 }}}, { Lu, 0, {{ 30.122866, 15.099346, 56.314899, 3.540980, 16.943729,-51.049416},
//{ Ge, +4, {{ 12.917200, 6.700030, 6.067910, 0.859041, 1.455720 }, { 1.883090, 10.342764, 0.000780, 89.559250, 0.183849, 0.000000}}},
// { 2.537180, 0.205855, 5.479130, 11.603000, 0.000000 }}}, { Hf, 0, {{ 30.617033, 15.145351, 54.933548, 4.096253, 16.896156,-49.719837},
//{ As, 0, {{ 16.672300, 6.070100, 3.431300, 4.277900, 2.531000 }, { 1.795613, 9.934469, 0.000739, 76.189705, 0.175914, 0.000000}}},
// { 2.634500, 0.264700, 12.947900, 47.797199, 0.000000 }}}, { Ta, 0, {{ 31.066359, 15.341823, 49.278297, 4.577665, 16.828321,-44.119026},
//{ Se, 0, {{ 17.000599, 5.819600, 3.973100, 4.354300, 2.840900 }, { 1.708732, 9.618455, 0.000760, 66.346199, 0.168002, 0.000000}}},
// { 2.409800, 0.272600, 15.237200, 43.816299, 0.000000 }}}, { W, 0, {{ 31.507900, 15.682498, 37.960129, 4.885509, 16.792112,-32.864574},
//{ Br, 0, {{ 17.178900, 5.235800, 5.637700, 3.985100, 2.955700 }, { 1.629485, 9.446448, 0.000898, 59.980675, 0.160798, 0.000000}}},
// { 2.172300, 16.579599, 0.260900, 41.432800, 0.000000 }}}, { Re, 0, {{ 31.888456, 16.117104, 42.390297, 5.211669, 16.767591,-37.412682},
//{ Br, -1, {{ 17.171799, 6.333800, 5.575400, 3.727200, 3.177600 }, { 1.549238, 9.233474, 0.000689, 54.516373, 0.152815, 0.000000}}},
// { 2.205900, 19.334499, 0.287100, 58.153500, 0.000000 }}}, { Os, 0, {{ 32.210297, 16.678440, 48.559906, 5.455839, 16.735533,-43.677956},
//{ Kr, 0, {{ 17.355499, 6.728600, 5.549300, 3.537500, 2.825000 }, { 1.473531, 9.049695, 0.000519, 50.210201, 0.145771, 0.000000}}},
// { 1.938400, 16.562300, 0.226100, 39.397202, 0.000000 }}}, { Ir, 0, {{ 32.004436, 1.975454, 17.070105, 15.939454, 5.990003, 4.018893},
//{ Rb, 0, {{ 17.178400, 9.643499, 5.139900, 1.529200, 3.487300 }, { 1.353767, 81.014175, 0.128093, 7.661196, 26.659403, 0.000000}}},
// { 1.788800, 17.315100, 0.274800, 164.933990, 0.000000 }}}, { Pt, 0, {{ 31.273891, 18.445440, 17.063745, 5.555933, 1.575270, 4.050394},
//{ Rb, +1, {{ 17.581600, 7.659800, 5.898100, 2.781700, 2.078200 }, { 1.316992, 8.797154, 0.124741, 40.177994, 1.316997, 0.000000}}},
// { 1.713900, 14.795700, 0.160300, 31.208700, 0.000000 }}}, { Au, 0, {{ 16.777390, 19.317156, 32.979683, 5.595453, 10.576854, -6.279078},
//{ Sr, 0, {{ 17.566299, 9.818399, 5.422000, 2.669400, 2.506400 }, { 0.122737, 8.621570, 1.256902, 38.008820, 0.000601, 0.000000}}},
// { 1.556400, 14.098800, 0.166400, 132.376007, 0.000000 }}}, { Hg, 0, {{ 16.839890, 20.023823, 28.428564, 5.881564, 4.714706, 4.076478},
//{ Sr, +2, {{ 18.087400, 8.137300, 2.565400, -34.193001, 41.402500 }, { 0.115905, 8.256927, 1.195250, 39.247227, 1.195250, 0.000000}}},
// { 1.490700, 12.696300, 24.565100, -0.013800, 0.000000 }}}, { Tl, 0, {{ 16.630795, 19.386616, 32.808571, 1.747191, 6.356862, 4.066939},
//{ Y, 0, {{ 17.775999, 10.294600, 5.726290, 3.265880, 1.912130 }, { 0.110704, 7.181401, 1.119730, 90.660263, 26.014978, 0.000000}}},
// { 1.402900, 12.800600, 0.125599, 104.353996, 0.000000 }}}, { Pb, 0, {{ 16.419567, 32.738590, 6.530247, 2.342742, 19.916475, 4.049824},
//{ Y, +3, {{ 17.926800, 9.153100, 1.767950, -33.108002, 40.260201 }, { 0.105499, 1.055049, 25.025890, 80.906593, 6.664449, 0.000000}}},
// { 1.354170, 11.214500, 22.659901, -0.013190, 0.000000 }}}, { Bi, 0, {{ 16.282274, 32.725136, 6.678302, 2.694750, 20.576559, 4.040914},
//{ Zr, 0, {{ 17.876499, 10.948000, 5.417320, 3.657210, 2.069290 }, { 0.101180, 1.002287, 25.714146, 77.057549, 6.291882, 0.000000}}},
// { 1.276180, 11.916000, 0.117622, 87.662697, 0.000000 }}}, { Po, 0, {{ 16.289164, 32.807171, 21.095163, 2.505901, 7.254589, 4.046556},
//{ Zr, +4, {{ 18.166800, 10.056200, 1.011180, -2.647900, 9.414539 }, { 0.098121, 0.966265, 6.046622, 76.598068, 28.096128, 0.000000}}},
// { 1.214800, 10.148300, 21.605400, -0.102760, 0.000000 }}}, { At, 0, {{ 16.011461, 32.615547, 8.113899, 2.884082, 21.377867, 3.995684},
//{ Nb, 0, {{ 17.614201, 12.014400, 4.041830, 3.533460, 3.755910 }, { 0.092639, 0.904416, 26.543257, 68.372963, 5.499512, 0.000000}}},
// { 1.188650, 11.766000, 0.204785, 69.795700, 0.000000 }}}, { Rn, 0, {{ 16.070229, 32.641106, 21.489658, 2.299218, 9.480184, 4.020977},
//{ Nb, +3, {{ 19.881199, 18.065300, 11.017700, 1.947150, -12.912000 }, { 0.090437, 0.876409, 5.239687, 69.188477, 27.632641, 0.000000}}},
// { 0.019175, 1.133050, 10.162100, 28.338900, 0.000000 }}}, { Fr, 0, {{ 16.007385, 32.663830, 21.594351, 1.598497, 11.121192, 4.003472},
//{ Nb, +5, {{ 17.916300, 13.341700, 10.799000, 0.337905, -6.393400 }, { 0.087031, 0.840187, 4.954467,199.805801, 26.905106, 0.000000}}},
// { 1.124460, 0.028781, 9.282060, 25.722799, 0.000000 }}}, { Ra, 0, {{ 32.563690, 21.396671, 11.298093, 2.834688, 15.914965, 3.981773},
//{ Mo, 0, {{ 3.702500, 17.235600, 12.887600, 3.742900, 4.387500 }, { 0.801980, 4.590666, 22.758972,160.404388, 0.083544, 0.000000}}},
// { 0.277200, 1.095800, 11.004000, 61.658401, 0.000000 }}}, { Ac, 0, {{ 15.914053, 32.535042, 21.553976, 11.433394, 3.612409, 3.939212},
//{ Mo, +3, {{ 21.166401, 18.201700, 11.742300, 2.309510, -14.421000 }, { 0.080511, 0.770669, 4.352206, 21.381622,130.500748, 0.000000}}},
// { 0.014734, 1.030310, 9.536590, 26.630699, 0.000000 }}}, { Th, 0, {{ 15.784024, 32.454899, 21.849222, 4.239077, 11.736191, 3.922533},
//{ Mo, +5, {{ 21.014900, 18.099199, 11.463200, 0.740625, -14.316000 }, { 0.077067, 0.735137, 4.097976,109.464111, 20.512138, 0.000000}}},
// { 0.014345, 1.022380, 8.788090, 23.345200, 0.000000 }}}, { Pa, 0, {{ 32.740208, 21.973675, 12.957398, 3.683832, 15.744058, 3.886066},
//{ Mo, +6, {{ 17.887100, 11.175000, 6.578910, 0.000000, 0.344941 }, { 0.709545, 4.050881, 19.231543,117.255005, 0.074040, 0.000000}}},
// { 1.036490, 8.480610, 0.058881, 0.000000, 0.000000 }}}, { U, 0, {{ 15.679275, 32.824306, 13.660459, 3.687261, 22.279434, 3.854444},
//{ Tc, 0, {{ 19.130100, 11.094800, 4.649010, 2.712630, 5.404280 }, { 0.071206, 0.681177, 18.236156,112.500038, 3.930325, 0.000000}}},
// { 0.864132, 8.144870, 21.570700, 86.847198, 0.000000 }}}, { Np, 0, {{ 32.999901, 22.638077, 14.219973, 3.672950, 15.683245, 3.769391},
//{ Ru, 0, {{ 19.267399, 12.918200, 4.863370, 1.567560, 5.378740 }, { 0.657086, 3.854918, 17.435474,109.464485, 0.068033, 0.000000}}},
// { 0.808520, 8.434669, 24.799700, 94.292801, 0.000000 }}}, { Pu, 0, {{ 33.281178, 23.148544, 15.153755, 3.031492, 15.704215, 3.664200},
//{ Ru, +3, {{ 18.563801, 13.288500, 9.326019, 3.009640, -3.189200 }, { 0.634999, 3.856168, 16.849735,121.292038, 0.064857, 0.000000}}},
// { 0.847329, 8.371640, 0.017662, 22.886999, 0.000000 }}}, { Am, 0, {{ 33.435162, 23.657259, 15.576339, 3.027023, 15.746100, 3.541160},
//{ Ru, +4, {{ 18.500299, 13.178699, 4.713040, 2.185350, 1.423570 }, { 0.612785, 3.792942, 16.195778,117.757004, 0.061755, 0.000000}}},
// { 0.844582, 8.125340, 0.364950, 20.850399, 0.000000 }}}, { Cm, 0, {{ 15.804837, 33.480801, 24.150198, 3.655563, 15.499866, 3.390840},
//{ Rh, 0, {{ 19.295700, 14.350100, 4.734250, 1.289180, 5.328000 }, { 0.058619, 0.590160, 3.674720,100.736191, 15.408296, 0.000000}}},
// { 0.751536, 8.217580, 25.874901, 98.606201, 0.000000 }}}, { Bk, 0, {{ 15.889072, 33.625286, 24.710381, 3.707139, 15.839268, 3.213169},
//{ Rh, +3, {{ 18.878500, 14.125900, 3.325150, -6.198900, 11.867800 }, { 0.055503, 0.569571, 3.615472, 97.694786, 14.754303, 0.000000}}},
// { 0.764252, 7.844380, 21.248699, -0.010360, 0.000000 }}}, { Cf, 0, {{ 33.794075, 25.467693, 16.048487, 3.657525, 16.008982, 3.005326},
//{ Rh, +4, {{ 18.854500, 13.980600, 2.534640, -5.652600, 11.283500 }, { 0.550447, 3.581973, 14.357388, 96.064972, 0.052450, 0.000000}}},
// { 0.760825, 7.624360, 19.331699, -0.010200, 0.000000 }}}, { H, -1, {{ 0.702260, 0.763666, 0.248678, 0.261323, 0.023017, 0.000425},
//{ Pd, 0, {{ 19.331900, 15.501699, 5.295370, 0.605844, 5.265930 }, { 23.945604, 74.897919, 6.773289,233.583450, 1.337531, 0.000000}}},
// { 0.698655, 7.989290, 25.205200, 76.898598, 0.000000 }}}, { Li, +1, {{ 0.432724, 0.549257, 0.376575, -0.336481, 0.976060, 0.001764},
//{ Pd, +2, {{ 19.170099, 15.209600, 4.322340, 0.000000, 5.291600 }, { 0.260367, 1.042836, 7.885294, 0.260368, 3.042539, 0.000000}}},
// { 0.696219, 7.555730, 22.505699, 0.000000, 0.000000 }}}, { Be, +2, {{ 3.055430, -2.372617, 1.044914, 0.544233, 0.381737, -0.653773},
//{ Pd, +4, {{ 19.249300, 14.790000, 2.892890, -7.949200, 13.017400 }, { 0.001226, 0.001227, 1.542106, 0.456279, 4.047479, 0.000000}}},
// { 0.683839, 7.148330, 17.914400, 0.005127, 0.000000 }}}, { C, AtomTypeTraits::kWKSFVal,
//{ Ag, 0, {{ 19.280800, 16.688499, 4.804500, 1.046300, 5.179000 }, {{ 1.258489, 0.728215, 1.119856, 2.168133, 0.705239, 0.019722},
// { 0.644600, 7.472600, 24.660500, 99.815598, 0.000000 }}}, { 10.683769, 0.208177, 0.836097, 24.603704, 58.954273, 0.000000}}},
//{ Ag, +1, {{ 19.181200, 15.971900, 5.274750, 0.357534, 5.215720 }, { O, -1, {{ 3.106934, 3.235142, 1.148886, 0.783981, 0.676953, 0.046136},
// { 0.646179, 7.191230, 21.732599, 66.114700, 0.000000 }}}, { 19.868080, 6.960252, 0.170043, 65.693512, 0.630757, 0.000000}}},
//{ Ag, +2, {{ 19.164299, 16.245600, 4.370900, 0.000000, 5.214040 }, { O, -2, {{ 3.990247, 2.300563, 0.607200, 1.907882, 1.167080, 0.025429},
// { 0.645643, 7.185440, 21.407200, 0.000000, 0.000000 }}}, { 16.639956, 5.636819, 0.108493, 47.299709, 0.379984, 0.000000}}},
//{ Cd, 0, {{ 19.221399, 17.644400, 4.461000, 1.602900, 5.069400 }, { F, -1, {{ 0.457649, 3.841561, 1.432771, 0.801876, 3.395041, 0.069525},
// { 0.594600, 6.908900, 24.700800, 87.482498, 0.000000 }}}, { 0.917243, 5.507803, 0.164955, 51.076206, 15.821679, 0.000000}}},
//{ Cd, +2, {{ 19.151400, 17.253500, 4.471280, 0.000000, 5.119370 }, { Na, +1, {{ 3.148690, 4.073989, 0.767888, 0.995612, 0.968249, 0.045300},
// { 0.597922, 6.806390, 20.252100, 0.000000, 0.000000 }}}, { 2.594987, 6.046925, 0.070139, 14.122657, 0.217037, 0.000000}}},
//{ In, 0, {{ 19.162399, 18.559601, 4.294800, 2.039600, 4.939100 }, { Mg, +2, {{ 3.062918, 4.135106, 0.853742, 1.036792, 0.852520, 0.058851},
// { 0.547600, 6.377600, 25.849899, 92.802902, 0.000000 }}}, { 2.015803, 4.417941, 0.065307, 9.669710, 0.187818, 0.000000}}},
//{ In, +3, {{ 19.104500, 18.110800, 3.788970, 0.000000, 4.996350 }, { Al, +3, {{ 4.132015, 0.912049, 1.102425, 0.614876, 3.219136, 0.019397},
// { 0.551522, 6.324700, 17.359501, 0.000000, 0.000000 }}}, { 3.528641, 7.378344, 0.133708, 0.039065, 1.644728, 0.000000}}},
//{ Sn, 0, {{ 19.188900, 19.100500, 4.458500, 2.466300, 4.782100 }, { Si, AtomTypeTraits::kWKSFVal,
// { 5.830300, 0.503100, 26.890900, 83.957100, 0.000000 }}}, {{ 2.879033, 3.072960, 1.515981, 1.390030, 4.995051, 0.146030},
//{ Sn, +2, {{ 19.109400, 19.054800, 4.564800, 0.487000, 4.786100 }, { 1.239713, 38.706276, 0.081481, 93.616333, 2.770293, 0.000000}}},
// { 0.503600, 5.837800, 23.375200, 62.206100, 0.000000 }}}, { Si, +4, {{ 3.676722, 3.828496, 1.258033, 0.419024, 0.720421, 0.097266},
//{ Sn, +4, {{ 18.933300, 19.713100, 3.418200, 0.019300, 3.918200 }, { 1.446851, 3.013144, 0.064397, 0.206254, 5.970222, 0.000000}}},
// { 5.764000, 0.465500, 14.004900, -0.758300, 0.000000 }}}, { Cl, -1, {{ 1.061802, 7.139886, 6.524271, 2.355626, 35.829403,-34.916603},
//{ Sb, 0, {{ 19.641800, 19.045500, 5.037100, 2.682700, 4.590900 }, { 0.144727, 1.171795, 19.467655, 60.320301, 0.000436, 0.000000}}},
// { 5.303400, 0.460700, 27.907400, 75.282501, 0.000000 }}}, { K, +1, {{-17.609339, 1.494873, 7.150305, 10.899569, 15.808228, 0.257164},
//{ Sb, +3, {{ 18.975500, 18.932999, 5.107890, 0.288753, 4.696260 }, { 18.840979, 0.053453, 0.812940, 22.264105, 14.351593, 0.000000}}},
// { 0.467196, 5.221260, 19.590200, 55.511299, 0.000000 }}}, { Ca, +2, {{ 8.501441, 12.880483, 9.765095, 7.156669, 0.711160,-21.013187},
//{ Sb, +5, {{ 19.868500, 19.030199, 2.412530, 0.000000, 4.692630 }, { 10.525848, -0.004033, 0.010692, 0.684443, 27.231771, 0.000000}}},
// { 5.448530, 0.467973, 14.125900, 0.000000, 0.000000 }}}, { Sc, +3, {{ 7.104348, 1.511488,-53.669773, 38.404816, 24.532240, 0.118642},
//{ Te, 0, {{ 19.964399, 19.013800, 6.144870, 2.523900, 4.352000 }, { 0.601957, 0.033386, 12.572138, 10.859736, 14.125230, 0.000000}}},
// { 4.817420, 0.420885, 28.528400, 70.840302, 0.000000 }}}, { Ti, +2, {{ 7.040119, 1.496285, 9.657304, 0.006534, 1.649561, 0.150362},
//{ I, 0, {{ 20.147200, 18.994900, 7.513800, 2.273500, 4.071200 }, { 0.537072, 0.031914, 8.009958,201.800293, 24.039482, 0.000000}}},
// { 4.347000, 0.381400, 27.765999, 66.877602, 0.000000 }}}, { Ti, +3, {{ 36.587933, 7.230255, -9.086077, 2.084594, 17.294008,-35.111282},
//{ I, -1, {{ 20.233200, 18.997000, 7.806900, 2.886800, 4.071400 }, { 0.000681, 0.522262, 5.262317, 15.881716, 6.149805, 0.000000}}},
// { 4.357900, 0.381500, 29.525900, 84.930397, 0.000000 }}}, { Ti, +4, {{ 45.355537, 7.092900, 7.483858,-43.498817, 1.678915, -0.110628},
//{ Xe, 0, {{ 20.293301, 19.029800, 8.976700, 1.990000, 3.711800 }, { 9.252186, 0.523046, 13.082852, 10.193876, 0.023064, 0.000000}}},
// { 3.928200, 0.344000, 26.465900, 64.265800, 0.000000 }}}, { V, +2, {{ 7.754356, 2.064100, 2.576998, 2.011404, 7.126177, -0.533379},
//{ Cs, 0, {{ 20.389200, 19.106199, 10.662000, 1.495300, 3.335200 }, { 7.066315, 0.014993, 7.066308, 22.055786, 0.467568, 0.000000}}},
// { 3.569000, 0.310700, 24.387899, 213.903992, 0.000000 }}}, { V, +3, {{ 9.958480, 1.596350, 1.483442,-10.846044, 17.332867, 0.474921},
//{ Cs, +1, {{ 20.352400, 19.127800, 10.282100, 0.961500, 3.279100 }, { 6.763041, 0.056895, 17.750029, 0.328826, 0.388013, 0.000000}}},
// { 3.552000, 0.308600, 23.712799, 59.456497, 0.000000 }}}, { V, +5, {{ 15.575018, 8.448095, 1.612040, -9.721855, 1.534029, 0.552676},
//{ Ba, 0, {{ 20.336100, 19.297001, 10.888000, 2.695900, 2.773100 }, { 0.682708, 5.566640, 10.527077, 0.907961, 0.066667, 0.000000}}},
// { 3.216000, 0.275600, 20.207300, 167.201996, 0.000000 }}}, { Cr, +2, {{ 10.598877, 1.565858, 2.728280, 0.098064, 6.959321, 0.049870},
//{ Ba, +2, {{ 20.180700, 19.113600, 10.905399, 0.776340, 3.029020 }, { 6.151846, 0.023519, 17.432816, 54.002388, 0.426301, 0.000000}}},
// { 3.213670, 0.283310, 20.055799, 51.745998, 0.000000 }}}, { Cr, +3, {{ 7.989310, 1.765079, 2.627125, 1.829380, 6.980908, -0.192123},
//{ La, 0, {{ 20.577999, 19.598999, 11.372700, 3.287190, 2.146780 }, { 6.068867, 0.018342, 6.068887, 16.309284, 0.420864, 0.000000}}},
// { 2.948170, 0.244475, 18.772600, 133.123993, 0.000000 }}}, { Mn, +2, {{ 11.287712, 26.042414, 3.058096, 0.090258, 7.088306,-24.566132},
//{ La, +3, {{ 20.248899, 19.376301, 11.632299, 0.336048, 2.408600 }, { 5.506225, 0.000774, 16.158575, 54.766354, 0.375580, 0.000000}}},
// { 2.920700, 0.250698, 17.821100, 54.945297, 0.000000 }}}, { Mn, +3, {{ 6.926972, 2.081342, 11.128379, 2.375107, -0.419287, -0.093713},
//{ Ce, 0, {{ 21.167099, 19.769501, 11.851299, 3.330490, 1.862640 }, { 0.378315, 0.015054, 5.379957, 14.429586, 0.004939, 0.000000}}},
// { 2.812190, 0.226836, 17.608299, 127.112999, 0.000000 }}}, { Mn, +4, {{ 12.409131, 7.466993, 1.809947,-12.138477, 10.780248, 0.672146},
//{ Ce, +3, {{ 20.803600, 19.559000, 11.936900, 0.612376, 2.090130 }, { 0.300400, 0.112814, 12.520756, 0.168653, 5.173237, 0.000000}}},
// { 2.776910, 0.231540, 16.540800, 43.169201, 0.000000 }}}, { Fe, +2, {{ 11.776765, 11.165097, 3.533495, 0.165345, 7.036932, -9.676919},
//{ Ce, +4, {{ 20.323500, 19.818600, 12.123300, 0.144583, 1.591800 }, { 4.912232, 0.001748, 14.166556, 42.381958, 0.341324, 0.000000}}},
// { 2.659410, 0.218850, 15.799200, 62.235500, 0.000000 }}}, { Fe, +3, {{ 9.721638, 63.403847, 2.141347, 2.629274, 7.033846,-61.930725},
//{ Pr, 0, {{ 22.043999, 19.669701, 12.385600, 2.824280, 2.058300 }, { 4.869297, 0.000293, 4.867602, 13.539076, 0.338520, 0.000000}}},
// { 2.773930, 0.222087, 16.766899, 143.643997, 0.000000 }}}, { Co, +2, {{ 6.993840, 26.285812, 12.254289, 0.246114, 4.017407,-24.796852},
//{ Pr, +3, {{ 21.372700, 19.749100, 12.132900, 0.975180, 1.771320 }, { 0.310779, 0.000684, 4.400528, 35.741447, 12.536393, 0.000000}}},
// { 2.645200, 0.214299, 15.323000, 36.406502, 0.000000 }}}, { Co, +3, {{ 6.861739, 2.678570, 12.281889, 3.501741, -0.179384, -1.147345},
//{ Pr, +4, {{ 20.941299, 20.053900, 12.466800, 0.296689, 1.242850 }, { 0.309794, 0.008142, 4.331703, 11.914167, 11.914167, 0.000000}}},
// { 2.544670, 0.202481, 14.813700, 45.464298, 0.000000 }}}, { Ni, +2, {{ 12.519017, 37.832058, 4.387257, 0.661552, 6.949072,-36.344471},
//{ Nd, 0, {{ 22.684500, 19.684700, 12.774000, 2.851370, 1.984860 }, { 3.933053, 0.000442, 10.449184, 23.860998, 0.283723, 0.000000}}},
// { 2.662480, 0.210628, 15.885000, 137.903000, 0.000000 }}}, { Ni, +3, {{ 13.579366, 1.902844, 12.859268, 3.811005, -6.838595, -0.317618},
//{ Nd, +3, {{ 21.961000, 19.933899, 12.120000, 1.510310, 1.475880 }, { 0.313140, 0.012621, 3.906407, 10.894311, 0.344379, 0.000000}}},
// { 2.527220, 0.199237, 14.178300, 30.871700, 0.000000 }}}, { Cu, +1, {{ 12.960763, 16.342150, 1.110102, 5.520682, 6.915452,-14.849320},
//{ Pm, 0, {{ 23.340500, 19.609501, 13.123500, 2.875160, 2.028760 }, { 3.576010, 0.000975, 29.523218, 10.114283, 0.261326, 0.000000}}},
// { 2.562700, 0.202088, 15.100900, 132.720993, 0.000000 }}}, { Cu, +2, {{ 11.895569, 16.344978, 5.799817, 1.048804, 6.789088,-14.878383},
//{ Pm, +3, {{ 22.552700, 20.110800, 12.067100, 2.074920, 1.194990 }, { 3.378519, 0.000924, 8.133653, 20.526524, 0.254741, 0.000000}}},
// { 2.417400, 0.185769, 13.127500, 27.449100, 0.000000 }}}, { Zn, +2, {{ 13.340772, 10.428857, 5.544489, 0.762295, 6.869172, -8.945248},
//{ Sm, 0, {{ 24.004200, 19.425800, 13.439600, 2.896040, 2.209630 }, { 3.215913, 0.001413, 8.542680, 21.891756, 0.239215, 0.000000}}},
// { 2.472740, 0.196451, 14.399600, 128.007004, 0.000000 }}}, { Ga, +3, {{ 13.123875, 35.288189, 6.126979, 0.611551, 6.724807,-33.875122},
//{ Sm, +3, {{ 23.150400, 20.259899, 11.920200, 2.714880, 0.954586 }, { 2.809960, 0.000323, 6.831534, 16.784311, 0.212002, 0.000000}}},
// { 2.316410, 0.174081, 12.157100, 24.824200, 0.000000 }}}, { Ge, +4, {{ 6.876636, 6.779091, 9.969591, 3.135857, 0.152389, 1.086542},
//{ Eu, 0, {{ 24.627399, 19.088600, 13.760300, 2.922700, 2.574500 }, { 2.025174, 0.176650, 3.573822, 7.685848, 16.677574, 0.000000}}},
// { 2.387900, 0.194200, 13.754600, 123.173996, 0.000000 }}}, { Br, -1, {{ 17.714310, 6.466926, 6.947385, 4.402674, -0.697279, 1.152674},
//{ Eu, +2, {{ 24.006300, 19.950399, 11.803400, 3.872430, 1.363890 }, { 2.122554, 19.050768, 0.152708, 58.690361, 58.690372, 0.000000}}},
// { 2.277830, 0.173530, 11.609600, 26.515600, 0.000000 }}}, { Rb, +1, {{ 17.684320, 7.761588, 6.680874, 2.668883, 0.070974, 1.133263},
//{ Eu, +3, {{ 23.749699, 20.374500, 11.850900, 3.265030, 0.759344 }, { 1.710209, 14.919863, 0.128542, 31.654478, 0.128543, 0.000000}}},
// { 2.222580, 0.163940, 11.311000, 22.996599, 0.000000 }}}, { Sr, +2, {{ 17.694973, 1.275762, 6.154252, 9.234786, 0.515995, 1.125309},
//{ Gd, 0, {{ 25.070900, 19.079800, 13.851800, 3.545450, 2.419600 }, { 1.550888, 30.133041, 0.118774, 13.821799, 0.118774, 0.000000}}},
// { 2.253410, 0.181951, 12.933100, 101.397995, 0.000000 }}}, { Y, +3, {{ 46.660366, 10.369686, 4.623042,-62.170834, 17.471146, 19.023842},
//{ Gd, +3, {{ 24.346600, 20.420799, 11.870800, 3.714900, 0.645089 }, { -0.019971, 13.180257, 0.176398, -0.016727, 1.467348, 0.000000}}},
// { 2.135530, 0.155525, 10.578199, 21.702900, 0.000000 }}}, { Zr, +4, {{ 6.802956, 17.699253, 10.650647, -0.248108, 0.250338, 0.827902},
//{ Tb, 0, {{ 25.897600, 18.218500, 14.316700, 2.953540, 3.582240 }, { 0.096228, 1.296127, 11.240715, -0.219259, -0.219021, 0.000000}}},
// { 2.242560, 0.196143, 12.664800, 115.362000, 0.000000 }}}, { Nb, +3, {{ 17.714323, 1.675213, 7.483963, 8.322464, 11.143573, -8.339573},
//{ Tb, +3, {{ 24.955900, 20.327099, 12.247100, 3.773000, 0.691967 }, { 1.172419, 30.102791, 0.080255, -0.002983, 10.456687, 0.000000}}},
// { 2.056010, 0.149525, 10.049900, 21.277300, 0.000000 }}}, { Nb, +5, {{ 17.580206, 7.633277, 10.793497, 0.180884, 67.837921,-68.024780},
//{ Dy, 0, {{ 26.507000, 17.638300, 14.559600, 2.965770, 4.297280 }, { 1.165852, 0.078558, 9.507652, 31.621656, -0.000438, 0.000000}}},
// { 2.180200, 0.202172, 12.189899, 111.874001, 0.000000 }}}, { Mo, +3, {{ 7.447050, 17.778122, 11.886068, 1.997905, 1.789626, -1.898764},
//{ Dy, +3, {{ 25.539499, 20.286100, 11.981200, 4.500730, 0.689690 }, { 0.072000, 1.073145, 9.834720, 28.221746, -0.011674, 0.000000}}},
// { 1.980400, 0.143384, 9.349720, 19.580999, 0.000000 }}}, { Mo, +5, {{ 7.929879, 17.667669, 11.515987, 0.500402, 77.444084,-78.056595},
//{ Ho, 0, {{ 26.904900, 17.293999, 14.558300, 3.638370, 4.567960 }, { 0.068856, 1.068064, 9.046229, 26.558945, -0.000473, 0.000000}}},
// { 2.070510, 0.197940, 11.440700, 92.656601, 0.000000 }}}, { Mo, +6, {{ 34.757683, 9.653037, 6.584769,-18.628115, 2.490594, 1.141916},
//{ Ho, +3, {{ 26.129601, 20.099400, 11.978800, 4.936760, 0.852795 }, { 1.301770, 7.123843, 0.094097, 1.617443, 12.335434, 0.000000}}},
// { 1.910720, 0.139358, 8.800180, 18.590799, 0.000000 }}}, { Ru, +3, {{ 17.894758, 13.579529, 10.729251, 2.474095, 48.227997,-51.905243},
//{ Er, 0, {{ 27.656300, 16.428499, 14.977900, 2.982330, 5.920460 }, { 0.902827, 8.740579, 0.045125, 24.764954, -0.001699, 0.000000}}},
// { 2.073560, 0.223545, 11.360400, 105.703003, 0.000000 }}}, { Ru, +4, {{ 17.845776, 13.455084, 10.229087, 1.653524, 14.059795,-17.241762},
//{ Er, +3, {{ 26.722000, 19.774799, 12.150600, 5.173790, 1.176130 }, { 0.901070, 8.482392, 0.045972, 23.015272, -0.004889, 0.000000}}},
// { 1.846590, 0.137290, 8.362249, 17.897400, 0.000000 }}}, { Rh, +3, {{ 17.758621, 14.569813, 5.298320, 2.533579, 0.879753, 0.960843},
//{ Tm, 0, {{ 28.181900, 15.885099, 15.154200, 2.987060, 6.756210 }, { 0.841779, 8.319533, 0.069050, 23.709131, 0.069050, 0.000000}}},
// { 2.028590, 0.238849, 10.997499, 102.960999, 0.000000 }}}, { Rh, +4, {{ 17.716188, 14.446654, 5.185801, 1.703448, 0.989992, 0.959941},
//{ Tm, +3, {{ 27.308300, 19.332001, 12.333900, 5.383480, 1.639290 }, { 0.840572, 8.100647, 0.068995, 22.357307, 0.068995, 0.000000}}},
// { 1.787110, 0.136974, 7.967780, 17.292200, 0.000000 }}}, { Pd, +2, {{ 6.122282, 15.651012, 3.513508, 9.060790, 8.771199, 0.879336},
//{ Yb, 0, {{ 28.664101, 15.434500, 15.308700, 2.989630, 7.566720 }, { 0.062424, 8.018296, 24.784275, 0.776457, 0.776457, 0.000000}}},
// { 1.988900, 0.257119, 10.664700, 100.417000, 0.000000 }}}, { Pd, +4, {{ 6.152421,-96.069023, 31.622141, 81.578255, 17.801403, 0.915874},
//{ Yb, +2, {{ 28.120899, 17.681700, 13.333500, 5.146570, 3.709830 }, { 0.063951, 11.090354, 13.466152, 9.758302, 0.783014, 0.000000}}},
// { 1.785030, 0.159970, 8.183040, 20.389999, 0.000000 }}}, { Ag, +1, {{ 6.091192, 4.019526, 16.948174, 4.258638, 13.889437, 0.785127},
//{ Yb, +3, {{ 27.891700, 18.761400, 12.607200, 5.476470, 2.260010 }, { 0.056305, 0.719340, 7.758938, 27.368349, 0.719340, 0.000000}}},
// { 1.732720, 0.138790, 7.644120, 16.815300, 0.000000 }}}, { Ag, +2, {{ 6.401808, 48.699802, 4.799859,-32.332523, 16.356710, 1.068247},
//{ Lu, 0, {{ 28.947599, 15.220800, 15.100000, 3.716010, 7.976280 }, { 0.068167, 0.942270, 20.639496, 1.100365, 6.883131, 0.000000}}},
// { 1.901820, 9.985189, 0.261033, 84.329803, 0.000000 }}}, { Cd, +2, {{ 6.093711, 43.909691, 17.041306,-39.675117, 17.958918, 0.664795},
//{ Lu, +3, {{ 28.462799, 18.121000, 12.842899, 5.594150, 2.975730 }, { 0.050624, 8.654143, 15.621396, 11.082067, 0.667591, 0.000000}}},
// { 1.682160, 0.142292, 7.337270, 16.353500, 0.000000 }}}, { In, +3, {{ 6.206277, 18.497746, 3.078131, 10.524613, 7.401234, 0.293677},
//{ Hf, 0, {{ 29.143999, 15.172600, 14.758600, 4.300130, 8.581540 }, { 0.041357, 6.605563, 18.792250, 0.608082, 0.608082, 0.000000}}},
// { 1.832620, 9.599899, 0.275116, 72.028999, 0.000000 }}}, { Sn, +2, {{ 6.353672, 4.770377, 14.672025, 4.235959, 18.002131, -0.042519},
//{ Hf, +4, {{ 28.813099, 18.460100, 12.728500, 5.599270, 2.396990 }, { 0.034720, 6.167891, 6.167879, 29.006456, 0.561774, 0.000000}}},
// { 1.591360, 0.128903, 6.762320, 14.036600, 0.000000 }}}, { Sn, +4, {{ 15.445732, 6.420892, 4.562980, 1.713385, 18.033537, -0.172219},
//{ Ta, 0, {{ 29.202400, 15.229300, 14.513500, 4.764920, 9.243540 }, { 6.280898, 0.033144, 6.280899, 17.983601, 0.557980, 0.000000}}},
// { 1.773330, 9.370460, 0.295977, 63.364399, 0.000000 }}}, { Sb, +3, {{ 10.189171, 57.461918, 19.356573, 4.862206,-45.394096, 1.516108},
//{ Ta, +5, {{ 29.158699, 18.840700, 12.826799, 5.386950, 1.785550 }, { 0.089485, 0.375256, 5.357987, 22.153736, 0.297768, 0.000000}}},
// { 1.507110, 0.116741, 6.315240, 12.424400, 0.000000 }}}, { Sb, +5, {{ 17.920622, 6.647932, 12.724075, 1.555545, 7.600591, -0.445371},
//{ W, 0, {{ 29.081800, 15.430000, 14.432700, 5.119820, 9.887500 }, { 0.522315, 0.029487, 5.718210, 16.433775, 5.718204, 0.000000}}},
// { 1.720290, 9.225900, 0.321703, 57.056000, 0.000000 }}}, { I, -1, {{ 20.010330, 17.835524, 8.104130, 2.231118, 9.158548, -3.341004},
//{ W, +6, {{ 29.493599, 19.376301, 13.054399, 5.064120, 1.010740 }, { 4.565931, 0.444266, 32.430672, 95.149040, 0.014906, 0.000000}}},
// { 1.427550, 0.104621, 5.936670, 11.197200, 0.000000 }}}, { Cs, +1, {{ 19.939056, 24.967621, 10.375884, 0.454243, 17.660248,-19.394306},
//{ Re, 0, {{ 28.762100, 15.718900, 14.556400, 5.441740, 10.472000 }, { 3.770511, 0.004040, 25.311275, 76.537766, 0.384730, 0.000000}}},
// { 1.671910, 9.092270, 0.350500, 52.086098, 0.000000 }}}, { Ba, +2, {{ 19.750200, 17.513683, 10.884892, 0.321585, 65.149834,-59.618172},
//{ Os, 0, {{ 28.189400, 16.154999, 14.930500, 5.675890, 11.000500 }, { 3.430748, 0.361590, 21.358307, 70.309402, 0.001418, 0.000000}}},
// { 1.629030, 8.979480, 0.382661, 48.164700, 0.000000 }}}, { La, +3, {{ 19.688887, 17.345703, 11.356296, 0.099418, 82.358124,-76.846909},
//{ Os, +4, {{ 30.418999, 15.263700, 14.745800, 5.067950, 6.498040 }, { 3.146211, 0.339586, 18.753832, 90.345459, 0.001072, 0.000000}}},
// { 1.371130, 6.847060, 0.165191, 18.003000, 0.000000 }}}, { Ce, +3, {{ 26.593231, 85.866432, -6.677695, 12.111847, 17.401903,-80.313423},
//{ Ir, 0, {{ 27.304899, 16.729599, 15.611500, 5.833770, 11.472200 }, { 3.280381, 0.001012, 4.313575, 17.868504, 0.326962, 0.000000}}},
// { 1.592790, 8.865530, 0.417916, 45.001099, 0.000000 }}}, { Ce, +4, {{ 17.457533, 25.659941, 11.691037, 19.695251,-16.994749, -3.515096},
//{ Ir, +3, {{ 30.415600, 15.862000, 13.614500, 5.820080, 8.279030 }, { 0.311812, -0.003793, 16.568687, 2.886395, -0.008931, 0.000000}}},
// { 1.343230, 7.109090, 0.204633, 20.325399, 0.000000 }}}, { Pr, +3, {{ 20.879841, 36.035797, 12.135341, 0.283103, 17.167803,-30.500784},
//{ Ir, +4, {{ 30.705799, 15.551200, 14.232600, 5.536720, 6.968240 }, { 2.870897, 0.002364, 16.615236, 53.909359, 0.306993, 0.000000}}},
// { 1.309230, 6.719830, 0.167252, 17.491100, 0.000000 }}}, { Pr, +4, {{ 17.496082, 21.538509, 20.403114, 12.062211, -7.492043, -9.016722},
//{ Pt, 0, {{ 27.005899, 17.763901, 15.713100, 5.783700, 11.688300 }, { 0.294457, -0.002742, 2.772886, 15.804613, -0.013556, 0.000000}}},
// { 1.512930, 8.811740, 0.424593, 38.610298, 0.000000 }}}, { Nd, +3, {{ 17.120077, 56.038139, 21.468307, 10.000671, 2.905866,-50.541992},
//{ Pt, +2, {{ 29.842899, 16.722401, 13.215300, 6.352340, 9.853290 }, { 0.291295, 0.001421, 2.743681, 14.581367, 22.485098, 0.000000}}},
// { 1.329270, 7.389790, 0.263297, 22.942600, 0.000000 }}}, { Pm, +3, {{ 22.221066, 17.068142, 12.805423, 0.435687, 52.238770,-46.767181},
//{ Pt, +4, {{ 30.961201, 15.982900, 13.734800, 5.920340, 7.395340 }, { 2.635767, 0.277039, 14.927315, 45.768017, 0.001455, 0.000000}}},
// { 1.248130, 6.608340, 0.168640, 16.939199, 0.000000 }}}, { Sm, +3, {{ 15.618565, 19.538092, 13.398946, -4.358811, 24.490461, -9.714854},
//{ Au, 0, {{ 16.881901, 18.591299, 25.558201, 5.860000, 12.065800 }, { 0.006001, 0.306379, 14.979594, 0.748825, 2.454492, 0.000000}}},
// { 0.461100, 8.621600, 1.482600, 36.395599, 0.000000 }}}, { Eu, +2, {{ 23.899035, 31.657497, 12.955752, 1.700576, 16.992199,-26.204315},
//{ Au, +1, {{ 28.010899, 17.820400, 14.335899, 6.580770, 11.229900 }, { 2.467332, 0.002230, 13.625002, 35.089481, 0.253136, 0.000000}}},
// { 1.353210, 7.739500, 0.356752, 26.404301, 0.000000 }}}, { Eu, +3, {{ 17.758327, 33.498665, 24.067188, 13.436883, -9.019134,-19.768026},
//{ Au, +3, {{ 30.688599, 16.902901, 12.780100, 6.523540, 9.096800 }, { 0.244474, -0.003901, 2.487526, 14.568011, -0.015628, 0.000000}}},
// { 1.219900, 6.828720, 0.212867, 18.659000, 0.000000 }}}, { Gd, +3, {{ 24.344999, 16.945311, 13.866931, 0.481674, 93.506378,-88.147179},
//{ Hg, 0, {{ 20.680901, 19.041700, 21.657499, 5.967600, 12.608900 }, { 2.333971, 0.239215, 12.982995, 43.876347, 0.000673, 0.000000}}},
// { 0.545000, 8.448400, 1.572900, 38.324600, 0.000000 }}}, { Tb, +3, {{ 24.878252, 16.856016, 13.663937, 1.279671, 39.271294,-33.950317},
//{ Hg, +1, {{ 25.085300, 18.497299, 16.888300, 6.482160, 12.020500 }, { 2.223301, 0.227290, 11.812528, 29.910065, 0.001527, 0.000000}}},
// { 1.395070, 7.651050, 0.443378, 28.226200, 0.000000 }}}, { Dy, +3, {{ 16.864344, 90.383461, 13.675473, 1.687078, 25.540651,-85.150650},
//{ Hg, +2, {{ 29.564100, 18.059999, 12.837400, 6.899120, 10.626800 }, { 0.216275, 0.000593, 11.121207, 26.250975, 2.135930, 0.000000}}},
// { 1.211520, 7.056390, 0.284738, 20.748199, 0.000000 }}}, { Ho, +3, {{ 16.837524, 63.221336, 13.703766, 2.061602, 26.202621,-58.026505},
//{ Tl, 0, {{ 27.544600, 19.158400, 15.538000, 5.525930, 13.174600 }, { 0.206873, 0.000796, 10.500283, 24.031883, 2.055060, 0.000000}}},
// { 0.655150, 8.707510, 1.963470, 45.814899, 0.000000 }}}, { Er, +3, {{ 16.810127, 22.681061, 13.864114, 2.294506, 26.864477,-17.513460},
//{ Tl, +1, {{ 21.398500, 20.472300, 18.747799, 6.828470, 12.525800 }, { 0.198293, 0.002126, 9.973341, 22.836388, 1.979442, 0.000000}}},
// { 1.471100, 0.517394, 7.434630, 28.848200, 0.000000 }}}, { Tm, +3, {{ 16.787500, 15.350905, 14.182357, 2.299111, 27.573771,-10.192087},
//{ Tl, +3, {{ 30.869499, 18.384100, 11.932800, 7.005740, 9.802700 }, { 0.190852, 0.003036, 9.602934, 22.526880, 1.912862, 0.000000}}},
// { 1.100800, 6.538520, 0.219074, 17.211399, 0.000000 }}}, { Yb, +2, {{ 28.443794, 16.849527, 14.165081, 3.445311, 28.308853,-23.214935},
//{ Pb, 0, {{ 31.061699, 13.063700, 18.441999, 5.969600, 13.411800 }, { 1.863896, 0.183811, 9.225469, 23.691355, 0.001463, 0.000000}}},
// { 0.690200, 2.357600, 8.618000, 47.257900, 0.000000 }}}, { Yb, +3, {{ 28.191629, 16.828087, 14.167848, 2.744962, 23.171774,-18.103676},
//{ Pb, +2, {{ 21.788601, 19.568199, 19.140600, 7.011070, 12.473400 }, { 1.842889, 0.182788, 9.045957, 20.799847, 0.001759, 0.000000}}},
// { 1.336600, 0.488383, 6.772700, 23.813200, 0.000000 }}}, { Lu, +3, {{ 28.828693, 16.823227, 14.247617, 3.079559, 25.647667,-20.626528},
//{ Pb, +4, {{ 32.124397, 18.800301, 12.017500, 6.968860, 8.084280 }, { 1.776641, 0.175560, 8.575531, 19.693701, 0.001453, 0.000000}}},
// { 1.005660, 6.109260, 0.147041, 14.714000, 0.000000 }}}, { Hf, +4, {{ 29.267378, 16.792543, 14.785310, 2.184128, 23.791996,-18.820383},
//{ Bi, 0, {{ 33.368900, 12.951000, 16.587700, 6.469200, 13.578199 }, { 1.697911, 0.168313, 8.190025, 18.277578, 0.001431, 0.000000}}},
// { 0.704000, 2.923800, 8.793700, 48.009300, 0.000000 }}}, { Ta, +5, {{ 29.539469, 16.741854, 15.182070, 1.642916, 16.437447,-11.542459},
//{ Bi, +3, {{ 21.805300, 19.502600, 19.105301, 7.102950, 12.471100 }, { 1.612934, 0.160460, 7.654408, 17.070732, 0.001858, 0.000000}}},
// { 1.235600, 6.241490, 0.469999, 20.318501, 0.000000 }}}, { W, +6, {{ 29.729357, 17.247808, 15.184488, 1.154652, 0.739335, 3.945157},
//{ Bi, +5, {{ 33.536400, 25.094601, 19.249699, 6.915550, -6.799400 }, { 1.501648, 0.140803, 6.880573, 14.299601, 14.299618, 0.000000}}},
// { 0.916540, 0.390420, 5.714140, 12.828500, 0.000000 }}}, { Os, +4, {{ 17.113485, 15.792370, 23.342392, 4.090271, 7.671292, 3.988390},
//{ Po, 0, {{ 34.672600, 15.473300, 13.113800, 7.025880, 13.677000 }, { 0.131850, 7.288542, 1.389307, 19.629425, 1.389307, 0.000000}}},
// { 0.700999, 3.550780, 9.556419, 47.004501, 0.000000 }}}, { Ir, +3, {{ 31.537575, 16.363338, 15.597141, 5.051404, 1.436935, 4.009459},
//{ At, 0, {{ 35.316299, 19.021099, 9.498870, 7.425180, 13.710800 }, { 1.334144, 7.451918, 0.127514, 21.705648, 0.127515, 0.000000}}},
// { 0.685870, 3.974580, 11.382400, 45.471500, 0.000000 }}}, { Ir, +4, {{ 30.391249, 16.146996, 17.019068, 4.458904, 0.975372, 4.006865},
//{ Rn, 0, {{ 35.563099, 21.281601, 8.003700, 7.443300, 13.690500 }, { 1.328519, 7.181766, 0.127337, 19.060146, 1.328519, 0.000000}}},
// { 0.663100, 4.069100, 14.042200, 44.247299, 0.000000 }}}, { Pt, +2, {{ 31.986849, 17.249048, 15.269374, 5.760234, 1.694079, 4.032512},
//{ Fr, 0, {{ 35.929901, 23.054699, 12.143900, 2.112530, 13.724700 }, { 1.281143, 7.625512, 0.123571, 24.190826, 0.123571, 0.000000}}},
// { 0.646453, 4.176190, 23.105200, 150.644989, 0.000000 }}}, { Pt, +4, {{ 41.932713, 16.339224, 17.653894, 6.012420,-12.036877, 4.094551},
//{ Ra, 0, {{ 35.763000, 22.906399, 12.473900, 3.210970, 13.621099 }, { 1.111409, 6.466086, 0.128917, 16.954155, 0.778721, 0.000000}}},
// { 0.616341, 3.871350, 19.988701, 142.324997, 0.000000 }}}, { Au, +1, {{ 32.124306, 16.716476, 16.814100, 7.311565, 0.993064, 4.040792},
//{ Ra, +2, {{ 35.215000, 21.670000, 7.913420, 7.650780, 13.543100 }, { 1.216073, 7.165378, 0.118715, 20.442486, 53.095985, 0.000000}}},
// { 0.604909, 3.576700, 12.601000, 29.843599, 0.000000 }}}, { Au, +3, {{ 31.704271, 17.545767, 16.819551, 5.522640, 0.361725, 4.042679},
//{ Ac, 0, {{ 35.659698, 23.103199, 12.597700, 4.086550, 13.526600 }, { 1.215561, 7.220506, 0.118812, 20.050970, 1.215562, 0.000000}}},
// { 0.589092, 3.651550, 18.598999, 117.019997, 0.000000 }}}, { Hg, +1, {{ 28.866837, 19.277540, 16.776051, 6.281459, 3.710289, 4.068430},
//{ Ac, +3, {{ 35.173599, 22.111200, 8.192160, 7.055450, 13.463699 }, { 1.173967, 7.583842, 0.115351, 29.055994, 1.173968, 0.000000}}},
// { 0.579689, 3.414370, 12.918700, 25.944300, 0.000000 }}}, { Hg, +2, {{ 32.411079, 18.690371, 16.711773, 9.974835, -3.847611, 4.052869},
//{ Th, 0, {{ 35.564499, 23.421900, 12.747300, 4.807030, 13.431400 }, { 1.162980, 7.329806, 0.114518, 22.009489, 22.009493, 0.000000}}},
// { 0.563359, 3.462040, 17.830900, 99.172195, 0.000000 }}}, { Tl, +1, {{ 32.295044, 16.570049, 17.991013, 1.535355, 7.554591, 4.054030},
//{ Th, +4, {{ 35.100700, 22.441799, 9.785540, 5.294440, 13.375999 }, { 1.101544, 0.110020, 6.528559, 52.495068, 20.338634, 0.000000}}},
// { 0.555054, 3.244980, 13.466100, 23.953300, 0.000000 }}}, { Tl, +3, {{ 32.525639, 19.139185, 17.100321, 5.891115, 12.599463, -9.256075},
//{ Pa, 0, {{ 35.884701, 23.294800, 14.189100, 4.172870, 13.428699 }, { 1.094966, 6.900992, 0.103667, 18.489614, -0.001401, 0.000000}}},
// { 0.547751, 3.415190, 16.923500, 105.250999, 0.000000 }}}, { Pb, +2, {{ 27.392647, 16.496822, 19.984501, 6.813923, 5.233910, 4.065623},
//{ U, 0, {{ 36.022800, 23.412800, 14.949100, 4.188000, 13.396600 }, { 1.058874, 0.106305, 6.708123, 24.395554, 1.058874, 0.000000}}},
// { 0.529300, 3.325300, 16.092699, 100.612999, 0.000000 }}}, { Pb, +4, {{ 32.505657, 20.014240, 14.645661, 5.029499, 1.760138, 4.044678},
//{ U, +3, {{ 35.574699, 22.525900, 12.216499, 5.370730, 13.309200 }, { 1.047035, 6.670321, 0.105279, 16.525040, 0.105279, 0.000000}}},
// { 0.520480, 3.122930, 12.714800, 26.339399, 0.000000 }}}, { Bi, +3, {{ 32.461437, 19.438683, 16.302486, 7.322662, 0.431704, 4.043703},
//{ U, +4, {{ 35.371498, 22.532600, 12.029100, 4.798400, 13.267099 }, { 0.997930, 6.038867, 0.101338, 18.371586, 46.361046, 0.000000}}},
// { 0.516598, 3.050530, 12.572300, 23.458200, 0.000000 }}}, { Bi, +5, {{ 16.734028, 20.580494, 9.452623, 61.155834,-34.041023, 4.113663},
//{ U, +6, {{ 34.850899, 22.758400, 14.009900, 1.214570, 13.166500 }, { 0.105076, 4.773282, 11.762162, 1.211775, 1.619408, 0.000000}}},
// { 0.507079, 2.890300, 13.176700, 25.201700, 0.000000 }}}, { Ra, +2, {{ 4.986228, 32.474945, 21.947443, 11.800013, 10.807292, 3.956572},
//{ Np, 0, {{ 36.187401, 23.596399, 15.640200, 4.185500, 13.357300 }, { 0.082597, 0.791468, 4.608034, 24.792431, 0.082597, 0.000000}}},
// { 0.511929, 3.253960, 15.362200, 97.490799, 0.000000 }}}, { Ac, +3, {{ 15.584983, 32.022125, 21.456327, 0.757593, 12.341252, 3.838984},
//{ Np, +3, {{ 35.707397, 22.612999, 12.989799, 5.432270, 13.254400 }, { 0.077438, 0.739963, 4.040735, 47.525002, 19.406845, 0.000000}}},
// { 0.502322, 3.038070, 12.144899, 25.492800, 0.000000 }}}, { Th, +4, {{ 15.515445, 32.090691, 13.996399, 12.918157, 7.635514, 3.831122},
//{ Np, +4, {{ 35.510300, 22.578699, 12.776600, 4.921590, 13.211599 }, { 0.074499, 0.711663, 3.871044, 18.596891, 3.871044, 0.000000}}},
// { 0.498626, 2.966270, 11.948400, 22.750200, 0.000000 }}}, { U, +3, {{ 15.360309, 32.395657, 21.961290, 1.325894, 14.251453, 3.706622},
//{ Np, +6, {{ 35.013599, 22.728600, 14.388400, 1.756690, 13.113000 }, { 0.067815, 0.654643, 3.643409, 39.604965, 16.330570, 0.000000}}},
// { 0.489810, 2.810990, 12.330000, 22.658100, 0.000000 }}}, { U, +4, {{ 15.355091, 32.235306, 0.557745, 14.396367, 21.751173, 3.705863},
//{ Pu, 0, {{ 36.525398, 23.808300, 16.770700, 3.479470, 13.381200 }, { 0.067789, 0.652613, 42.354237, 15.908239, 3.553231, 0.000000}}},
// { 0.499384, 3.263710, 14.945499, 105.979996, 0.000000 }}}, { U, +6, {{ 15.333844, 31.770849, 21.274414, 13.872636, 0.048519, 3.700591},
//{ Pu, +3, {{ 35.840000, 22.716900, 13.580700, 5.660160, 13.199100 }, { 0.067644, 0.646384, 3.317894, 14.650250, 75.339699, 0.000000}}},
// { 0.484936, 2.961180, 11.533100, 24.399200, 0.000000 }}}, { Np, +3, {{ 15.378152, 32.572132, 22.206125, 1.413295, 14.828381, 3.603370},
//{ Pu, +4, {{ 35.649300, 22.646000, 13.359500, 5.188310, 13.155500 }, { 0.064613, 0.631420, 3.561936, 37.875511, 15.546129, 0.000000}}},
// { 0.481422, 2.890200, 11.316000, 21.830099, 0.000000 }}}, { Np, +4, {{ 15.373926, 32.423019, 21.969994, 0.662078, 14.969350, 3.603039},
//{ Pu, +6, {{ 35.173599, 22.718100, 14.763500, 2.286780, 13.058200 }, { 0.064597, 0.629658, 3.476389, 39.438942, 15.135764, 0.000000}}},
// { 0.473204, 2.738480, 11.552999, 20.930300, 0.000000 }}}, { Np, +6, {{ 15.359986, 31.992825, 21.412458, 0.066574, 14.568174, 3.600942},
//{ Am, 0, {{ 36.670601, 24.099199, 17.341499, 3.493310, 13.359200 }, { 0.064528, 0.624505, 3.253441, 67.658318, 13.980832, 0.000000}}},
// { 0.483629, 3.206470, 14.313600, 102.272995, 0.000000 }}}, { Pu, +3, {{ 15.356004, 32.769127, 22.680210, 1.351055, 15.416232, 3.428895},
//{ Cm, 0, {{ 36.648800, 24.409599, 17.399000, 4.216650, 13.288700 }, { 0.060590, 0.604663, 3.491509, 37.260635, 14.981921, 0.000000}}},
// { 0.465154, 3.089970, 13.434600, 88.483398, 0.000000 }}}, { Pu, +4, {{ 15.416219, 32.610569, 22.256662, 0.719495, 15.518152, 3.480408},
//{ Bk, 0, {{ 36.788101, 24.773600, 17.891899, 4.232840, 13.275400 }, { 0.061456, 0.607938, 3.411848, 37.628792, 14.464360, 0.000000}}},
// { 0.451018, 3.046190, 12.894600, 86.002998, 0.000000 }}}, { Pu, +6, {{ 15.436506, 32.289719, 14.726737, 15.012391, 7.024677, 3.502325},
//{ Cf, 0, {{ 36.918499, 25.199499, 18.331699, 4.243910, 13.267400 }, { 0.061815, 0.606541, 3.245363, 13.616438, 3.245364, 0.000000}}}
// { 0.437533, 3.007750, 12.404400, 83.788101, 0.000000}}},
{ H, 0, {{ 0.413048, 0.294953, 0.187491, 0.080701, 0.023736, 0.000049},
{ 15.569946, 32.398468, 5.711404, 61.889874, 1.334118, 0.000000}}},
{ He, 0, {{ 0.732354, 0.753896, 0.283819, 0.190003, 0.039139, 0.000487},
{ 11.553918, 4.595831, 1.546299, 26.463964, 0.377523, 0.000000}}},
{ Li, 0, {{ 0.974637, 0.158472, 0.811855, 0.262416, 0.790108, 0.002542},
{ 4.334946, 0.342451, 97.102966,201.363831, 1.409234, 0.000000}}},
{ Be, 0, {{ 1.533712, 0.638283, 0.601052, 0.106139, 1.118414, 0.002511},
{ 42.662079, 0.595420, 99.106499, 0.151340, 1.843093, 0.000000}}},
{ B, 0, {{ 2.085185, 1.064580, 1.062788, 0.140515, 0.641784, 0.003823},
{ 23.494068, 1.137894, 61.238976, 0.114886, 0.399036, 0.000000}}},
{ C, 0, {{ 2.657506, 1.078079, 1.490909, -4.241070, 0.713791, 4.297983},
{ 14.780758, 0.776775, 42.086842, -0.000294, 0.239535, 0.000000}}},
{ N, 0, {{ 11.893780, 3.277479, 1.858092, 0.858927, 0.912985,-11.804902},
{ 0.000158, 10.232723, 30.344690, 0.656065, 0.217287, 0.000000}}},
{ O, 0, {{ 2.960427, 2.508818, 0.637853, 0.722838, 1.142756, 0.027014},
{ 14.182259, 5.936858, 0.112726, 34.958481, 0.390240, 0.000000}}},
{ F, 0, {{ 3.511943, 2.772244, 0.678385, 0.915159, 1.089261, 0.032557},
{ 10.687859, 4.380466, 0.093982, 27.255203, 0.313066, 0.000000}}},
{ Ne, 0, {{ 4.183749, 2.905726, 0.520513, 1.135641, 1.228065, 0.025576},
{ 8.175457, 3.252536, 0.063295, 21.813910, 0.224952, 0.000000}}},
{ Na, 0, {{ 4.910127, 3.081783, 1.262067, 1.098938, 0.560991, 0.079712},
{ 3.281434, 9.119178, 0.102763,132.013947, 0.405878, 0.000000}}},
{ Mg, 0, {{ 4.708971, 1.194814, 1.558157, 1.170413, 3.239403, 0.126842},
{ 4.875207,108.506081, 0.111516, 48.292408, 1.928171, 0.000000}}},
{ Al, 0, {{ 4.730796, 2.313951, 1.541980, 1.117564, 3.154754, 0.139509},
{ 3.628931, 43.051167, 0.095960,108.932388, 1.555918, 0.000000}}},
{ Si, 0, {{ 5.275329, 3.191038, 1.511514, 1.356849, 2.519114, 0.145073},
{ 2.631338, 33.730728, 0.081119, 86.288643, 1.170087, 0.000000}}},
{ P, 0, {{ 1.950541, 4.146930, 1.494560, 1.522042, 5.729711, 0.155233},
{ 0.908139, 27.044952, 0.071280, 67.520187, 1.981173, 0.000000}}},
{ S, 0, {{ 6.372157, 5.154568, 1.473732, 1.635073, 1.209372, 0.154722},
{ 1.514347, 22.092527, 0.061373, 55.445175, 0.646925, 0.000000}}},
{ Cl, 0, {{ 1.446071, 6.870609, 6.151801, 1.750347, 0.634168, 0.146773},
{ 0.052357, 1.193165, 18.343416, 46.398396, 0.401005, 0.000000}}},
{ Ar, 0, {{ 7.188004, 6.638454, 0.454180, 1.929593, 1.523654, 0.265954},
{ 0.956221, 15.339877, 15.339862, 39.043823, 0.062409, 0.000000}}},
{ K, 0, {{ 8.163991, 7.146945, 1.070140, 0.877316, 1.486434, 0.253614},
{ 12.816323, 0.808945,210.327011, 39.597652, 0.052821, 0.000000}}},
{ Ca, 0, {{ 8.593655, 1.477324, 1.436254, 1.182839, 7.113258, 0.196255},
{ 10.460644, 0.041891, 81.390381,169.847839, 0.688098, 0.000000}}},
{ Sc, 0, {{ 1.476566, 1.487278, 1.600187, 9.177463, 7.099750, 0.157765},
{ 53.131023, 0.035325,137.319489, 9.098031, 0.602102, 0.000000}}},
{ Ti, 0, {{ 9.818524, 1.522646, 1.703101, 1.768774, 7.082555, 0.102473},
{ 8.001879, 0.029763, 39.885422,120.157997, 0.532405, 0.000000}}},
{ V, 0, {{ 10.473575, 1.547881, 1.986381, 1.865616, 7.056250, 0.067744},
{ 7.081940, 0.026040, 31.909672,108.022842, 0.474882, 0.000000}}},
{ Cr, 0, {{ 11.007069, 1.555477, 2.985293, 1.347855, 7.034779, 0.065510},
{ 6.366281, 0.023987, 23.244839,105.774498, 0.429369, 0.000000}}},
{ Mn, 0, {{ 11.709542, 1.733414, 2.673141, 2.023368, 7.003180, -0.147293},
{ 5.597120, 0.017800, 21.788420, 89.517914, 0.383054, 0.000000}}},
{ Fe, 0, {{ 12.311098, 1.876623, 3.066177, 2.070451, 6.975185, -0.304931},
{ 5.009415, 0.014461, 18.743040, 82.767876, 0.346506, 0.000000}}},
{ Co, 0, {{ 12.914510, 2.481908, 3.466894, 2.106351, 6.960892, -0.936572},
{ 4.507138, 0.009126, 16.438129, 76.987320, 0.314418, 0.000000}}},
{ Ni, 0, {{ 13.521865, 6.947285, 3.866028, 2.135900, 4.284731, -2.762697},
{ 4.077277, 0.286763, 14.622634, 71.966080, 0.004437, 0.000000}}},
{ Cu, 0, {{ 14.014192, 4.784577, 5.056806, 1.457971, 6.932996, -3.254477},
{ 3.738280, 0.003744, 13.034982, 72.554794, 0.265666, 0.000000}}},
{ Zn, 0, {{ 14.741002, 6.907748, 4.642337, 2.191766, 38.424042,-36.915829},
{ 3.388232, 0.243315, 11.903689, 63.312130, 0.000397, 0.000000}}},
{ Ga, 0, {{ 15.758946, 6.841123, 4.121016, 2.714681, 2.395246, -0.847395},
{ 3.121754, 0.226057, 12.482196, 66.203621, 0.007238, 0.000000}}},
{ Ge, 0, {{ 16.540613, 1.567900, 3.727829, 3.345098, 6.785079, 0.018726},
{ 2.866618, 0.012198, 13.432163, 58.866047, 0.210974, 0.000000}}},
{ As, 0, {{ 17.025642, 4.503441, 3.715904, 3.937200, 6.790175, -2.984117},
{ 2.597739, 0.003012, 14.272119, 50.437996, 0.193015, 0.000000}}},
{ Se, 0, {{ 17.354071, 4.653248, 4.259489, 4.136455, 6.749163, -3.160982},
{ 2.349787, 0.002550, 15.579460, 45.181202, 0.177432, 0.000000}}},
{ Br, 0, {{ 17.550570, 5.411882, 3.937180, 3.880645, 6.707793, -2.492088},
{ 2.119226, 16.557184, 0.002481, 42.164009, 0.162121, 0.000000}}},
{ Kr, 0, {{ 17.655279, 6.848105, 4.171004, 3.446760, 6.685200, -2.810592},
{ 1.908231, 16.606236, 0.001598, 39.917473, 0.146896, 0.000000}}},
{ Rb, 0, {{ 8.123134, 2.138042, 6.761702, 1.156051, 17.679546, 1.139548},
{ 15.142385, 33.542667, 0.129372,224.132507, 1.713368, 0.000000}}},
{ Sr, 0, {{ 17.730219, 9.795867, 6.099763, 2.620025, 0.600053, 1.140251},
{ 1.563060, 14.310868, 0.120574,135.771317, 0.120574, 0.000000}}},
{ Y, 0, {{ 17.792040, 10.253252, 5.714949, 3.170516, 0.918251, 1.131787},
{ 1.429691, 13.132816, 0.112173,108.197029, 0.112173, 0.000000}}},
{ Zr, 0, {{ 17.859772, 10.911038, 5.821115, 3.512513, 0.746965, 1.124859},
{ 1.310692, 12.319285, 0.104353, 91.777542, 0.104353, 0.000000}}},
{ Nb, 0, {{ 17.958399, 12.063054, 5.007015, 3.287667, 1.531019, 1.123452},
{ 1.211590, 12.246687, 0.098615, 75.011948, 0.098615, 0.000000}}},
{ Mo, 0, {{ 6.236218, 17.987711, 12.973127, 3.451426, 0.210899, 1.108770},
{ 0.090780, 1.108310, 11.468720, 66.684151, 0.090780, 0.000000}}},
{ Tc, 0, {{ 17.840963, 3.428236, 1.373012, 12.947364, 6.335469, 1.074784},
{ 1.005729, 41.901382,119.320541, 9.781542, 0.083391, 0.000000}}},
{ Ru, 0, {{ 6.271624, 17.906738, 14.123269, 3.746008, 0.908235, 1.043992},
{ 0.077040, 0.928222, 9.555345, 35.860680,123.552246, 0.000000}}},
{ Rh, 0, {{ 6.216648, 17.919739, 3.854252, 0.840326, 15.173498, 0.995452},
{ 0.070789, 0.856121, 33.889484,121.686691, 9.029517, 0.000000}}},
{ Pd, 0, {{ 6.121511, 4.784063, 16.631683, 4.318258, 13.246773, 0.883099},
{ 0.062549, 0.784031, 8.751391, 34.489983, 0.784031, 0.000000}}},
{ Ag, 0, {{ 6.073874, 17.155437, 4.173344, 0.852238, 17.988686, 0.756603},
{ 0.055333, 7.896512, 28.443739,110.376106, 0.716809, 0.000000}}},
{ Cd, 0, {{ 6.080986, 18.019468, 4.018197, 1.303510, 17.974669, 0.603504},
{ 0.048990, 7.273646, 29.119284, 95.831207, 0.661231, 0.000000}}},
{ In, 0, {{ 6.196477, 18.816183, 4.050479, 1.638929, 17.962912, 0.333097},
{ 0.042072, 6.695665, 31.009790,103.284348, 0.610714, 0.000000}}},
{ Sn, 0, {{ 19.325171, 6.281571, 4.498866, 1.856934, 17.917318, 0.119024},
{ 6.118104, 0.036915, 32.529045, 95.037186, 0.565651, 0.000000}}},
{ Sb, 0, {{ 5.394956, 6.549570, 19.650681, 1.827820, 17.867832, -0.290506},
{ 33.326523, 0.030974, 5.564929, 87.130966, 0.523992, 0.000000}}},
{ Te, 0, {{ 6.660302, 6.940756, 19.847015, 1.557175, 17.802427, -0.806668},
{ 33.031654, 0.025750, 5.065547, 84.101616, 0.487660, 0.000000}}},
{ I, 0, {{ 19.884502, 6.736593, 8.110516, 1.170953, 17.548716, -0.448811},
{ 4.628591, 0.027754, 31.849096, 84.406387, 0.463550, 0.000000}}},
{ Xe, 0, {{ 19.978920, 11.774945, 9.332182, 1.244749, 17.737501, -6.065902},
{ 4.143356, 0.010142, 28.796200, 75.280685, 0.413616, 0.000000}}},
{ Cs, 0, {{ 17.418674, 8.314444, 10.323193, 1.383834, 19.876251, -2.322802},
{ 0.399828, 0.016872, 25.605827,233.339676, 3.826915, 0.000000}}},
{ Ba, 0, {{ 19.747343, 17.368477, 10.465718, 2.592602, 11.003653, -5.183497},
{ 3.481823, 0.371224, 21.226641,173.834274, 0.010719, 0.000000}}},
{ La, 0, {{ 19.966019, 27.329655, 11.018425, 3.086696, 17.335455,-21.745489},
{ 3.197408, 0.003446, 19.955492,141.381973, 0.341817, 0.000000}}},
{ Ce, 0, {{ 17.355122, 43.988499, 20.546650, 3.130670, 11.353665,-38.386017},
{ 0.328369, 0.002047, 3.088196,134.907654, 18.832960, 0.000000}}},
{ Pr, 0, {{ 21.551311, 17.161730, 11.903859, 2.679103, 9.564197, -3.871068},
{ 2.995675, 0.312491, 17.716705,152.192825, 0.010468, 0.000000}}},
{ Nd, 0, {{ 17.331244, 62.783924, 12.160097, 2.663483, 22.239950,-57.189842},
{ 0.300269, 0.001320, 17.026001,148.748993, 2.910268, 0.000000}}},
{ Pm, 0, {{ 17.286388, 51.560162, 12.478557, 2.675515, 22.960947,-45.973682},
{ 0.286620, 0.001550, 16.223755,143.984512, 2.796480, 0.000000}}},
{ Sm, 0, {{ 23.700363, 23.072214, 12.777782, 2.684217, 17.204367,-17.452166},
{ 2.689539, 0.003491, 15.495437,139.862473, 0.274536, 0.000000}}},
{ Eu, 0, {{ 17.186195, 37.156837, 13.103387, 2.707246, 24.419271,-31.586687},
{ 0.261678, 0.001995, 14.787360,134.816299, 2.581883, 0.000000}}},
{ Gd, 0, {{ 24.898117, 17.104952, 13.222581, 3.266152, 48.995213,-43.505684},
{ 2.435028, 0.246961, 13.996325,110.863091, 0.001383, 0.000000}}},
{ Tb, 0, {{ 25.910013, 32.344139, 13.765117, 2.751404, 17.064405,-26.851971},
{ 2.373912, 0.002034, 13.481969,125.836510, 0.236916, 0.000000}}},
{ Dy, 0, {{ 26.671785, 88.687576, 14.065445, 2.768497, 17.067781,-83.279831},
{ 2.282593, 0.000665, 12.920230,121.937187, 0.225531, 0.000000}}},
{ Ho, 0, {{ 27.150190, 16.999819, 14.059334, 3.386979, 46.546471,-41.165253},
{ 2.169660, 0.215414, 12.213148,100.506783, 0.001211, 0.000000}}},
{ Er, 0, {{ 28.174887, 82.493271, 14.624002, 2.802756, 17.018515,-77.135223},
{ 2.120995, 0.000640, 11.915256,114.529938, 0.207519, 0.000000}}},
{ Tm, 0, {{ 28.925894, 76.173798, 14.904704, 2.814812, 16.998117,-70.839813},
{ 2.046203, 0.000656, 11.465375,111.411980, 0.199376, 0.000000}}},
{ Yb, 0, {{ 29.676760, 65.624069, 15.160854, 2.830288, 16.997850,-60.313812},
{ 1.977630, 0.000720, 11.044622,108.139153, 0.192110, 0.000000}}},
{ Lu, 0, {{ 30.122866, 15.099346, 56.314899, 3.540980, 16.943729,-51.049416},
{ 1.883090, 10.342764, 0.000780, 89.559250, 0.183849, 0.000000}}},
{ Hf, 0, {{ 30.617033, 15.145351, 54.933548, 4.096253, 16.896156,-49.719837},
{ 1.795613, 9.934469, 0.000739, 76.189705, 0.175914, 0.000000}}},
{ Ta, 0, {{ 31.066359, 15.341823, 49.278297, 4.577665, 16.828321,-44.119026},
{ 1.708732, 9.618455, 0.000760, 66.346199, 0.168002, 0.000000}}},
{ W, 0, {{ 31.507900, 15.682498, 37.960129, 4.885509, 16.792112,-32.864574},
{ 1.629485, 9.446448, 0.000898, 59.980675, 0.160798, 0.000000}}},
{ Re, 0, {{ 31.888456, 16.117104, 42.390297, 5.211669, 16.767591,-37.412682},
{ 1.549238, 9.233474, 0.000689, 54.516373, 0.152815, 0.000000}}},
{ Os, 0, {{ 32.210297, 16.678440, 48.559906, 5.455839, 16.735533,-43.677956},
{ 1.473531, 9.049695, 0.000519, 50.210201, 0.145771, 0.000000}}},
{ Ir, 0, {{ 32.004436, 1.975454, 17.070105, 15.939454, 5.990003, 4.018893},
{ 1.353767, 81.014175, 0.128093, 7.661196, 26.659403, 0.000000}}},
{ Pt, 0, {{ 31.273891, 18.445440, 17.063745, 5.555933, 1.575270, 4.050394},
{ 1.316992, 8.797154, 0.124741, 40.177994, 1.316997, 0.000000}}},
{ Au, 0, {{ 16.777390, 19.317156, 32.979683, 5.595453, 10.576854, -6.279078},
{ 0.122737, 8.621570, 1.256902, 38.008820, 0.000601, 0.000000}}},
{ Hg, 0, {{ 16.839890, 20.023823, 28.428564, 5.881564, 4.714706, 4.076478},
{ 0.115905, 8.256927, 1.195250, 39.247227, 1.195250, 0.000000}}},
{ Tl, 0, {{ 16.630795, 19.386616, 32.808571, 1.747191, 6.356862, 4.066939},
{ 0.110704, 7.181401, 1.119730, 90.660263, 26.014978, 0.000000}}},
{ Pb, 0, {{ 16.419567, 32.738590, 6.530247, 2.342742, 19.916475, 4.049824},
{ 0.105499, 1.055049, 25.025890, 80.906593, 6.664449, 0.000000}}},
{ Bi, 0, {{ 16.282274, 32.725136, 6.678302, 2.694750, 20.576559, 4.040914},
{ 0.101180, 1.002287, 25.714146, 77.057549, 6.291882, 0.000000}}},
{ Po, 0, {{ 16.289164, 32.807171, 21.095163, 2.505901, 7.254589, 4.046556},
{ 0.098121, 0.966265, 6.046622, 76.598068, 28.096128, 0.000000}}},
{ At, 0, {{ 16.011461, 32.615547, 8.113899, 2.884082, 21.377867, 3.995684},
{ 0.092639, 0.904416, 26.543257, 68.372963, 5.499512, 0.000000}}},
{ Rn, 0, {{ 16.070229, 32.641106, 21.489658, 2.299218, 9.480184, 4.020977},
{ 0.090437, 0.876409, 5.239687, 69.188477, 27.632641, 0.000000}}},
{ Fr, 0, {{ 16.007385, 32.663830, 21.594351, 1.598497, 11.121192, 4.003472},
{ 0.087031, 0.840187, 4.954467,199.805801, 26.905106, 0.000000}}},
{ Ra, 0, {{ 32.563690, 21.396671, 11.298093, 2.834688, 15.914965, 3.981773},
{ 0.801980, 4.590666, 22.758972,160.404388, 0.083544, 0.000000}}},
{ Ac, 0, {{ 15.914053, 32.535042, 21.553976, 11.433394, 3.612409, 3.939212},
{ 0.080511, 0.770669, 4.352206, 21.381622,130.500748, 0.000000}}},
{ Th, 0, {{ 15.784024, 32.454899, 21.849222, 4.239077, 11.736191, 3.922533},
{ 0.077067, 0.735137, 4.097976,109.464111, 20.512138, 0.000000}}},
{ Pa, 0, {{ 32.740208, 21.973675, 12.957398, 3.683832, 15.744058, 3.886066},
{ 0.709545, 4.050881, 19.231543,117.255005, 0.074040, 0.000000}}},
{ U, 0, {{ 15.679275, 32.824306, 13.660459, 3.687261, 22.279434, 3.854444},
{ 0.071206, 0.681177, 18.236156,112.500038, 3.930325, 0.000000}}},
{ Np, 0, {{ 32.999901, 22.638077, 14.219973, 3.672950, 15.683245, 3.769391},
{ 0.657086, 3.854918, 17.435474,109.464485, 0.068033, 0.000000}}},
{ Pu, 0, {{ 33.281178, 23.148544, 15.153755, 3.031492, 15.704215, 3.664200},
{ 0.634999, 3.856168, 16.849735,121.292038, 0.064857, 0.000000}}},
{ Am, 0, {{ 33.435162, 23.657259, 15.576339, 3.027023, 15.746100, 3.541160},
{ 0.612785, 3.792942, 16.195778,117.757004, 0.061755, 0.000000}}},
{ Cm, 0, {{ 15.804837, 33.480801, 24.150198, 3.655563, 15.499866, 3.390840},
{ 0.058619, 0.590160, 3.674720,100.736191, 15.408296, 0.000000}}},
{ Bk, 0, {{ 15.889072, 33.625286, 24.710381, 3.707139, 15.839268, 3.213169},
{ 0.055503, 0.569571, 3.615472, 97.694786, 14.754303, 0.000000}}},
{ Cf, 0, {{ 33.794075, 25.467693, 16.048487, 3.657525, 16.008982, 3.005326},
{ 0.550447, 3.581973, 14.357388, 96.064972, 0.052450, 0.000000}}},
{ H, -1, {{ 0.702260, 0.763666, 0.248678, 0.261323, 0.023017, 0.000425},
{ 23.945604, 74.897919, 6.773289,233.583450, 1.337531, 0.000000}}},
{ Li, +1, {{ 0.432724, 0.549257, 0.376575, -0.336481, 0.976060, 0.001764},
{ 0.260367, 1.042836, 7.885294, 0.260368, 3.042539, 0.000000}}},
{ Be, +2, {{ 3.055430, -2.372617, 1.044914, 0.544233, 0.381737, -0.653773},
{ 0.001226, 0.001227, 1.542106, 0.456279, 4.047479, 0.000000}}},
{ C, AtomTypeTraits::kWKSFVal,
{{ 1.258489, 0.728215, 1.119856, 2.168133, 0.705239, 0.019722},
{ 10.683769, 0.208177, 0.836097, 24.603704, 58.954273, 0.000000}}},
{ O, -1, {{ 3.106934, 3.235142, 1.148886, 0.783981, 0.676953, 0.046136},
{ 19.868080, 6.960252, 0.170043, 65.693512, 0.630757, 0.000000}}},
{ O, -2, {{ 3.990247, 2.300563, 0.607200, 1.907882, 1.167080, 0.025429},
{ 16.639956, 5.636819, 0.108493, 47.299709, 0.379984, 0.000000}}},
{ F, -1, {{ 0.457649, 3.841561, 1.432771, 0.801876, 3.395041, 0.069525},
{ 0.917243, 5.507803, 0.164955, 51.076206, 15.821679, 0.000000}}},
{ Na, +1, {{ 3.148690, 4.073989, 0.767888, 0.995612, 0.968249, 0.045300},
{ 2.594987, 6.046925, 0.070139, 14.122657, 0.217037, 0.000000}}},
{ Mg, +2, {{ 3.062918, 4.135106, 0.853742, 1.036792, 0.852520, 0.058851},
{ 2.015803, 4.417941, 0.065307, 9.669710, 0.187818, 0.000000}}},
{ Al, +3, {{ 4.132015, 0.912049, 1.102425, 0.614876, 3.219136, 0.019397},
{ 3.528641, 7.378344, 0.133708, 0.039065, 1.644728, 0.000000}}},
{ Si, AtomTypeTraits::kWKSFVal,
{{ 2.879033, 3.072960, 1.515981, 1.390030, 4.995051, 0.146030},
{ 1.239713, 38.706276, 0.081481, 93.616333, 2.770293, 0.000000}}},
{ Si, +4, {{ 3.676722, 3.828496, 1.258033, 0.419024, 0.720421, 0.097266},
{ 1.446851, 3.013144, 0.064397, 0.206254, 5.970222, 0.000000}}},
{ Cl, -1, {{ 1.061802, 7.139886, 6.524271, 2.355626, 35.829403,-34.916603},
{ 0.144727, 1.171795, 19.467655, 60.320301, 0.000436, 0.000000}}},
{ K, +1, {{-17.609339, 1.494873, 7.150305, 10.899569, 15.808228, 0.257164},
{ 18.840979, 0.053453, 0.812940, 22.264105, 14.351593, 0.000000}}},
{ Ca, +2, {{ 8.501441, 12.880483, 9.765095, 7.156669, 0.711160,-21.013187},
{ 10.525848, -0.004033, 0.010692, 0.684443, 27.231771, 0.000000}}},
{ Sc, +3, {{ 7.104348, 1.511488,-53.669773, 38.404816, 24.532240, 0.118642},
{ 0.601957, 0.033386, 12.572138, 10.859736, 14.125230, 0.000000}}},
{ Ti, +2, {{ 7.040119, 1.496285, 9.657304, 0.006534, 1.649561, 0.150362},
{ 0.537072, 0.031914, 8.009958,201.800293, 24.039482, 0.000000}}},
{ Ti, +3, {{ 36.587933, 7.230255, -9.086077, 2.084594, 17.294008,-35.111282},
{ 0.000681, 0.522262, 5.262317, 15.881716, 6.149805, 0.000000}}},
{ Ti, +4, {{ 45.355537, 7.092900, 7.483858,-43.498817, 1.678915, -0.110628},
{ 9.252186, 0.523046, 13.082852, 10.193876, 0.023064, 0.000000}}},
{ V, +2, {{ 7.754356, 2.064100, 2.576998, 2.011404, 7.126177, -0.533379},
{ 7.066315, 0.014993, 7.066308, 22.055786, 0.467568, 0.000000}}},
{ V, +3, {{ 9.958480, 1.596350, 1.483442,-10.846044, 17.332867, 0.474921},
{ 6.763041, 0.056895, 17.750029, 0.328826, 0.388013, 0.000000}}},
{ V, +5, {{ 15.575018, 8.448095, 1.612040, -9.721855, 1.534029, 0.552676},
{ 0.682708, 5.566640, 10.527077, 0.907961, 0.066667, 0.000000}}},
{ Cr, +2, {{ 10.598877, 1.565858, 2.728280, 0.098064, 6.959321, 0.049870},
{ 6.151846, 0.023519, 17.432816, 54.002388, 0.426301, 0.000000}}},
{ Cr, +3, {{ 7.989310, 1.765079, 2.627125, 1.829380, 6.980908, -0.192123},
{ 6.068867, 0.018342, 6.068887, 16.309284, 0.420864, 0.000000}}},
{ Mn, +2, {{ 11.287712, 26.042414, 3.058096, 0.090258, 7.088306,-24.566132},
{ 5.506225, 0.000774, 16.158575, 54.766354, 0.375580, 0.000000}}},
{ Mn, +3, {{ 6.926972, 2.081342, 11.128379, 2.375107, -0.419287, -0.093713},
{ 0.378315, 0.015054, 5.379957, 14.429586, 0.004939, 0.000000}}},
{ Mn, +4, {{ 12.409131, 7.466993, 1.809947,-12.138477, 10.780248, 0.672146},
{ 0.300400, 0.112814, 12.520756, 0.168653, 5.173237, 0.000000}}},
{ Fe, +2, {{ 11.776765, 11.165097, 3.533495, 0.165345, 7.036932, -9.676919},
{ 4.912232, 0.001748, 14.166556, 42.381958, 0.341324, 0.000000}}},
{ Fe, +3, {{ 9.721638, 63.403847, 2.141347, 2.629274, 7.033846,-61.930725},
{ 4.869297, 0.000293, 4.867602, 13.539076, 0.338520, 0.000000}}},
{ Co, +2, {{ 6.993840, 26.285812, 12.254289, 0.246114, 4.017407,-24.796852},
{ 0.310779, 0.000684, 4.400528, 35.741447, 12.536393, 0.000000}}},
{ Co, +3, {{ 6.861739, 2.678570, 12.281889, 3.501741, -0.179384, -1.147345},
{ 0.309794, 0.008142, 4.331703, 11.914167, 11.914167, 0.000000}}},
{ Ni, +2, {{ 12.519017, 37.832058, 4.387257, 0.661552, 6.949072,-36.344471},
{ 3.933053, 0.000442, 10.449184, 23.860998, 0.283723, 0.000000}}},
{ Ni, +3, {{ 13.579366, 1.902844, 12.859268, 3.811005, -6.838595, -0.317618},
{ 0.313140, 0.012621, 3.906407, 10.894311, 0.344379, 0.000000}}},
{ Cu, +1, {{ 12.960763, 16.342150, 1.110102, 5.520682, 6.915452,-14.849320},
{ 3.576010, 0.000975, 29.523218, 10.114283, 0.261326, 0.000000}}},
{ Cu, +2, {{ 11.895569, 16.344978, 5.799817, 1.048804, 6.789088,-14.878383},
{ 3.378519, 0.000924, 8.133653, 20.526524, 0.254741, 0.000000}}},
{ Zn, +2, {{ 13.340772, 10.428857, 5.544489, 0.762295, 6.869172, -8.945248},
{ 3.215913, 0.001413, 8.542680, 21.891756, 0.239215, 0.000000}}},
{ Ga, +3, {{ 13.123875, 35.288189, 6.126979, 0.611551, 6.724807,-33.875122},
{ 2.809960, 0.000323, 6.831534, 16.784311, 0.212002, 0.000000}}},
{ Ge, +4, {{ 6.876636, 6.779091, 9.969591, 3.135857, 0.152389, 1.086542},
{ 2.025174, 0.176650, 3.573822, 7.685848, 16.677574, 0.000000}}},
{ Br, -1, {{ 17.714310, 6.466926, 6.947385, 4.402674, -0.697279, 1.152674},
{ 2.122554, 19.050768, 0.152708, 58.690361, 58.690372, 0.000000}}},
{ Rb, +1, {{ 17.684320, 7.761588, 6.680874, 2.668883, 0.070974, 1.133263},
{ 1.710209, 14.919863, 0.128542, 31.654478, 0.128543, 0.000000}}},
{ Sr, +2, {{ 17.694973, 1.275762, 6.154252, 9.234786, 0.515995, 1.125309},
{ 1.550888, 30.133041, 0.118774, 13.821799, 0.118774, 0.000000}}},
{ Y, +3, {{ 46.660366, 10.369686, 4.623042,-62.170834, 17.471146, 19.023842},
{ -0.019971, 13.180257, 0.176398, -0.016727, 1.467348, 0.000000}}},
{ Zr, +4, {{ 6.802956, 17.699253, 10.650647, -0.248108, 0.250338, 0.827902},
{ 0.096228, 1.296127, 11.240715, -0.219259, -0.219021, 0.000000}}},
{ Nb, +3, {{ 17.714323, 1.675213, 7.483963, 8.322464, 11.143573, -8.339573},
{ 1.172419, 30.102791, 0.080255, -0.002983, 10.456687, 0.000000}}},
{ Nb, +5, {{ 17.580206, 7.633277, 10.793497, 0.180884, 67.837921,-68.024780},
{ 1.165852, 0.078558, 9.507652, 31.621656, -0.000438, 0.000000}}},
{ Mo, +3, {{ 7.447050, 17.778122, 11.886068, 1.997905, 1.789626, -1.898764},
{ 0.072000, 1.073145, 9.834720, 28.221746, -0.011674, 0.000000}}},
{ Mo, +5, {{ 7.929879, 17.667669, 11.515987, 0.500402, 77.444084,-78.056595},
{ 0.068856, 1.068064, 9.046229, 26.558945, -0.000473, 0.000000}}},
{ Mo, +6, {{ 34.757683, 9.653037, 6.584769,-18.628115, 2.490594, 1.141916},
{ 1.301770, 7.123843, 0.094097, 1.617443, 12.335434, 0.000000}}},
{ Ru, +3, {{ 17.894758, 13.579529, 10.729251, 2.474095, 48.227997,-51.905243},
{ 0.902827, 8.740579, 0.045125, 24.764954, -0.001699, 0.000000}}},
{ Ru, +4, {{ 17.845776, 13.455084, 10.229087, 1.653524, 14.059795,-17.241762},
{ 0.901070, 8.482392, 0.045972, 23.015272, -0.004889, 0.000000}}},
{ Rh, +3, {{ 17.758621, 14.569813, 5.298320, 2.533579, 0.879753, 0.960843},
{ 0.841779, 8.319533, 0.069050, 23.709131, 0.069050, 0.000000}}},
{ Rh, +4, {{ 17.716188, 14.446654, 5.185801, 1.703448, 0.989992, 0.959941},
{ 0.840572, 8.100647, 0.068995, 22.357307, 0.068995, 0.000000}}},
{ Pd, +2, {{ 6.122282, 15.651012, 3.513508, 9.060790, 8.771199, 0.879336},
{ 0.062424, 8.018296, 24.784275, 0.776457, 0.776457, 0.000000}}},
{ Pd, +4, {{ 6.152421,-96.069023, 31.622141, 81.578255, 17.801403, 0.915874},
{ 0.063951, 11.090354, 13.466152, 9.758302, 0.783014, 0.000000}}},
{ Ag, +1, {{ 6.091192, 4.019526, 16.948174, 4.258638, 13.889437, 0.785127},
{ 0.056305, 0.719340, 7.758938, 27.368349, 0.719340, 0.000000}}},
{ Ag, +2, {{ 6.401808, 48.699802, 4.799859,-32.332523, 16.356710, 1.068247},
{ 0.068167, 0.942270, 20.639496, 1.100365, 6.883131, 0.000000}}},
{ Cd, +2, {{ 6.093711, 43.909691, 17.041306,-39.675117, 17.958918, 0.664795},
{ 0.050624, 8.654143, 15.621396, 11.082067, 0.667591, 0.000000}}},
{ In, +3, {{ 6.206277, 18.497746, 3.078131, 10.524613, 7.401234, 0.293677},
{ 0.041357, 6.605563, 18.792250, 0.608082, 0.608082, 0.000000}}},
{ Sn, +2, {{ 6.353672, 4.770377, 14.672025, 4.235959, 18.002131, -0.042519},
{ 0.034720, 6.167891, 6.167879, 29.006456, 0.561774, 0.000000}}},
{ Sn, +4, {{ 15.445732, 6.420892, 4.562980, 1.713385, 18.033537, -0.172219},
{ 6.280898, 0.033144, 6.280899, 17.983601, 0.557980, 0.000000}}},
{ Sb, +3, {{ 10.189171, 57.461918, 19.356573, 4.862206,-45.394096, 1.516108},
{ 0.089485, 0.375256, 5.357987, 22.153736, 0.297768, 0.000000}}},
{ Sb, +5, {{ 17.920622, 6.647932, 12.724075, 1.555545, 7.600591, -0.445371},
{ 0.522315, 0.029487, 5.718210, 16.433775, 5.718204, 0.000000}}},
{ I, -1, {{ 20.010330, 17.835524, 8.104130, 2.231118, 9.158548, -3.341004},
{ 4.565931, 0.444266, 32.430672, 95.149040, 0.014906, 0.000000}}},
{ Cs, +1, {{ 19.939056, 24.967621, 10.375884, 0.454243, 17.660248,-19.394306},
{ 3.770511, 0.004040, 25.311275, 76.537766, 0.384730, 0.000000}}},
{ Ba, +2, {{ 19.750200, 17.513683, 10.884892, 0.321585, 65.149834,-59.618172},
{ 3.430748, 0.361590, 21.358307, 70.309402, 0.001418, 0.000000}}},
{ La, +3, {{ 19.688887, 17.345703, 11.356296, 0.099418, 82.358124,-76.846909},
{ 3.146211, 0.339586, 18.753832, 90.345459, 0.001072, 0.000000}}},
{ Ce, +3, {{ 26.593231, 85.866432, -6.677695, 12.111847, 17.401903,-80.313423},
{ 3.280381, 0.001012, 4.313575, 17.868504, 0.326962, 0.000000}}},
{ Ce, +4, {{ 17.457533, 25.659941, 11.691037, 19.695251,-16.994749, -3.515096},
{ 0.311812, -0.003793, 16.568687, 2.886395, -0.008931, 0.000000}}},
{ Pr, +3, {{ 20.879841, 36.035797, 12.135341, 0.283103, 17.167803,-30.500784},
{ 2.870897, 0.002364, 16.615236, 53.909359, 0.306993, 0.000000}}},
{ Pr, +4, {{ 17.496082, 21.538509, 20.403114, 12.062211, -7.492043, -9.016722},
{ 0.294457, -0.002742, 2.772886, 15.804613, -0.013556, 0.000000}}},
{ Nd, +3, {{ 17.120077, 56.038139, 21.468307, 10.000671, 2.905866,-50.541992},
{ 0.291295, 0.001421, 2.743681, 14.581367, 22.485098, 0.000000}}},
{ Pm, +3, {{ 22.221066, 17.068142, 12.805423, 0.435687, 52.238770,-46.767181},
{ 2.635767, 0.277039, 14.927315, 45.768017, 0.001455, 0.000000}}},
{ Sm, +3, {{ 15.618565, 19.538092, 13.398946, -4.358811, 24.490461, -9.714854},
{ 0.006001, 0.306379, 14.979594, 0.748825, 2.454492, 0.000000}}},
{ Eu, +2, {{ 23.899035, 31.657497, 12.955752, 1.700576, 16.992199,-26.204315},
{ 2.467332, 0.002230, 13.625002, 35.089481, 0.253136, 0.000000}}},
{ Eu, +3, {{ 17.758327, 33.498665, 24.067188, 13.436883, -9.019134,-19.768026},
{ 0.244474, -0.003901, 2.487526, 14.568011, -0.015628, 0.000000}}},
{ Gd, +3, {{ 24.344999, 16.945311, 13.866931, 0.481674, 93.506378,-88.147179},
{ 2.333971, 0.239215, 12.982995, 43.876347, 0.000673, 0.000000}}},
{ Tb, +3, {{ 24.878252, 16.856016, 13.663937, 1.279671, 39.271294,-33.950317},
{ 2.223301, 0.227290, 11.812528, 29.910065, 0.001527, 0.000000}}},
{ Dy, +3, {{ 16.864344, 90.383461, 13.675473, 1.687078, 25.540651,-85.150650},
{ 0.216275, 0.000593, 11.121207, 26.250975, 2.135930, 0.000000}}},
{ Ho, +3, {{ 16.837524, 63.221336, 13.703766, 2.061602, 26.202621,-58.026505},
{ 0.206873, 0.000796, 10.500283, 24.031883, 2.055060, 0.000000}}},
{ Er, +3, {{ 16.810127, 22.681061, 13.864114, 2.294506, 26.864477,-17.513460},
{ 0.198293, 0.002126, 9.973341, 22.836388, 1.979442, 0.000000}}},
{ Tm, +3, {{ 16.787500, 15.350905, 14.182357, 2.299111, 27.573771,-10.192087},
{ 0.190852, 0.003036, 9.602934, 22.526880, 1.912862, 0.000000}}},
{ Yb, +2, {{ 28.443794, 16.849527, 14.165081, 3.445311, 28.308853,-23.214935},
{ 1.863896, 0.183811, 9.225469, 23.691355, 0.001463, 0.000000}}},
{ Yb, +3, {{ 28.191629, 16.828087, 14.167848, 2.744962, 23.171774,-18.103676},
{ 1.842889, 0.182788, 9.045957, 20.799847, 0.001759, 0.000000}}},
{ Lu, +3, {{ 28.828693, 16.823227, 14.247617, 3.079559, 25.647667,-20.626528},
{ 1.776641, 0.175560, 8.575531, 19.693701, 0.001453, 0.000000}}},
{ Hf, +4, {{ 29.267378, 16.792543, 14.785310, 2.184128, 23.791996,-18.820383},
{ 1.697911, 0.168313, 8.190025, 18.277578, 0.001431, 0.000000}}},
{ Ta, +5, {{ 29.539469, 16.741854, 15.182070, 1.642916, 16.437447,-11.542459},
{ 1.612934, 0.160460, 7.654408, 17.070732, 0.001858, 0.000000}}},
{ W, +6, {{ 29.729357, 17.247808, 15.184488, 1.154652, 0.739335, 3.945157},
{ 1.501648, 0.140803, 6.880573, 14.299601, 14.299618, 0.000000}}},
{ Os, +4, {{ 17.113485, 15.792370, 23.342392, 4.090271, 7.671292, 3.988390},
{ 0.131850, 7.288542, 1.389307, 19.629425, 1.389307, 0.000000}}},
{ Ir, +3, {{ 31.537575, 16.363338, 15.597141, 5.051404, 1.436935, 4.009459},
{ 1.334144, 7.451918, 0.127514, 21.705648, 0.127515, 0.000000}}},
{ Ir, +4, {{ 30.391249, 16.146996, 17.019068, 4.458904, 0.975372, 4.006865},
{ 1.328519, 7.181766, 0.127337, 19.060146, 1.328519, 0.000000}}},
{ Pt, +2, {{ 31.986849, 17.249048, 15.269374, 5.760234, 1.694079, 4.032512},
{ 1.281143, 7.625512, 0.123571, 24.190826, 0.123571, 0.000000}}},
{ Pt, +4, {{ 41.932713, 16.339224, 17.653894, 6.012420,-12.036877, 4.094551},
{ 1.111409, 6.466086, 0.128917, 16.954155, 0.778721, 0.000000}}},
{ Au, +1, {{ 32.124306, 16.716476, 16.814100, 7.311565, 0.993064, 4.040792},
{ 1.216073, 7.165378, 0.118715, 20.442486, 53.095985, 0.000000}}},
{ Au, +3, {{ 31.704271, 17.545767, 16.819551, 5.522640, 0.361725, 4.042679},
{ 1.215561, 7.220506, 0.118812, 20.050970, 1.215562, 0.000000}}},
{ Hg, +1, {{ 28.866837, 19.277540, 16.776051, 6.281459, 3.710289, 4.068430},
{ 1.173967, 7.583842, 0.115351, 29.055994, 1.173968, 0.000000}}},
{ Hg, +2, {{ 32.411079, 18.690371, 16.711773, 9.974835, -3.847611, 4.052869},
{ 1.162980, 7.329806, 0.114518, 22.009489, 22.009493, 0.000000}}},
{ Tl, +1, {{ 32.295044, 16.570049, 17.991013, 1.535355, 7.554591, 4.054030},
{ 1.101544, 0.110020, 6.528559, 52.495068, 20.338634, 0.000000}}},
{ Tl, +3, {{ 32.525639, 19.139185, 17.100321, 5.891115, 12.599463, -9.256075},
{ 1.094966, 6.900992, 0.103667, 18.489614, -0.001401, 0.000000}}},
{ Pb, +2, {{ 27.392647, 16.496822, 19.984501, 6.813923, 5.233910, 4.065623},
{ 1.058874, 0.106305, 6.708123, 24.395554, 1.058874, 0.000000}}},
{ Pb, +4, {{ 32.505657, 20.014240, 14.645661, 5.029499, 1.760138, 4.044678},
{ 1.047035, 6.670321, 0.105279, 16.525040, 0.105279, 0.000000}}},
{ Bi, +3, {{ 32.461437, 19.438683, 16.302486, 7.322662, 0.431704, 4.043703},
{ 0.997930, 6.038867, 0.101338, 18.371586, 46.361046, 0.000000}}},
{ Bi, +5, {{ 16.734028, 20.580494, 9.452623, 61.155834,-34.041023, 4.113663},
{ 0.105076, 4.773282, 11.762162, 1.211775, 1.619408, 0.000000}}},
{ Ra, +2, {{ 4.986228, 32.474945, 21.947443, 11.800013, 10.807292, 3.956572},
{ 0.082597, 0.791468, 4.608034, 24.792431, 0.082597, 0.000000}}},
{ Ac, +3, {{ 15.584983, 32.022125, 21.456327, 0.757593, 12.341252, 3.838984},
{ 0.077438, 0.739963, 4.040735, 47.525002, 19.406845, 0.000000}}},
{ Th, +4, {{ 15.515445, 32.090691, 13.996399, 12.918157, 7.635514, 3.831122},
{ 0.074499, 0.711663, 3.871044, 18.596891, 3.871044, 0.000000}}},
{ U, +3, {{ 15.360309, 32.395657, 21.961290, 1.325894, 14.251453, 3.706622},
{ 0.067815, 0.654643, 3.643409, 39.604965, 16.330570, 0.000000}}},
{ U, +4, {{ 15.355091, 32.235306, 0.557745, 14.396367, 21.751173, 3.705863},
{ 0.067789, 0.652613, 42.354237, 15.908239, 3.553231, 0.000000}}},
{ U, +6, {{ 15.333844, 31.770849, 21.274414, 13.872636, 0.048519, 3.700591},
{ 0.067644, 0.646384, 3.317894, 14.650250, 75.339699, 0.000000}}},
{ Np, +3, {{ 15.378152, 32.572132, 22.206125, 1.413295, 14.828381, 3.603370},
{ 0.064613, 0.631420, 3.561936, 37.875511, 15.546129, 0.000000}}},
{ Np, +4, {{ 15.373926, 32.423019, 21.969994, 0.662078, 14.969350, 3.603039},
{ 0.064597, 0.629658, 3.476389, 39.438942, 15.135764, 0.000000}}},
{ Np, +6, {{ 15.359986, 31.992825, 21.412458, 0.066574, 14.568174, 3.600942},
{ 0.064528, 0.624505, 3.253441, 67.658318, 13.980832, 0.000000}}},
{ Pu, +3, {{ 15.356004, 32.769127, 22.680210, 1.351055, 15.416232, 3.428895},
{ 0.060590, 0.604663, 3.491509, 37.260635, 14.981921, 0.000000}}},
{ Pu, +4, {{ 15.416219, 32.610569, 22.256662, 0.719495, 15.518152, 3.480408},
{ 0.061456, 0.607938, 3.411848, 37.628792, 14.464360, 0.000000}}},
{ Pu, +6, {{ 15.436506, 32.289719, 14.726737, 15.012391, 7.024677, 3.502325},
{ 0.061815, 0.606541, 3.245363, 13.616438, 3.245364, 0.000000}}}
}; };
SFDataArrayElement kELSFData[] = { SFDataArrayElement kELSFData[] = {
......
/*- /*-
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
* *
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this * 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer * list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...@@ -24,14 +24,14 @@ ...@@ -24,14 +24,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <fstream>
#include <algorithm> #include <algorithm>
#include <fstream>
#include <mutex> #include <mutex>
#include "cif++/BondMap.hpp"
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/Compound.hpp"
#include "cif++/CifUtils.hpp" #include "cif++/CifUtils.hpp"
#include "cif++/BondMap.hpp" #include "cif++/Compound.hpp"
namespace mmcif namespace mmcif
{ {
...@@ -39,223 +39,79 @@ namespace mmcif ...@@ -39,223 +39,79 @@ namespace mmcif
namespace namespace
{ {
union IDType union IDType
{
IDType() : id_n(0){}
IDType(const IDType& rhs) : id_n(rhs.id_n) {}
IDType(const std::string& s)
: IDType()
{
assert(s.length() <= 4);
if (s.length() > 4)
throw BondMapException("Atom ID '" + s + "' is too long");
std::copy(s.begin(), s.end(), id_s);
}
IDType& operator=(const IDType& rhs)
{
id_n = rhs.id_n;
return *this;
}
IDType& operator=(const std::string& s)
{ {
id_n = 0; IDType()
assert(s.length() <= 4); : id_n(0)
if (s.length() > 4) {
throw BondMapException("Atom ID '" + s + "' is too long"); }
std::copy(s.begin(), s.end(), id_s); IDType(const IDType &rhs)
return *this; : id_n(rhs.id_n)
} {
}
bool operator<(const IDType& rhs) const IDType(const std::string &s)
{ : IDType()
return id_n < rhs.id_n; {
} assert(s.length() <= 4);
if (s.length() > 4)
bool operator<=(const IDType& rhs) const throw BondMapException("Atom ID '" + s + "' is too long");
{ std::copy(s.begin(), s.end(), id_s);
return id_n <= rhs.id_n; }
}
bool operator==(const IDType& rhs) const
{
return id_n == rhs.id_n;
}
bool operator!=(const IDType& rhs) const
{
return id_n != rhs.id_n;
}
char id_s[4];
uint32_t id_n;
};
static_assert(sizeof(IDType) == 4, "atom_id_type should be 4 bytes");
}
// // --------------------------------------------------------------------
// void createBondInfoFile(const fs::path& components, const fs::path& infofile)
// {
// std::ofstream outfile(infofile.string() + ".tmp", std::ios::binary);
// if (not outfile.is_open())
// throw BondMapException("Could not create bond info file " + infofile.string() + ".tmp");
// cif::File infile(components);
// std::set<atom_id_type> atomIDs;
// std::vector<atom_id_type> compoundIDs;
// for (auto& db: infile)
// {
// auto chem_comp_bond = db.get("chem_comp_bond");
// if (not chem_comp_bond)
// {
// if (cif::VERBOSE > 1)
// std::cerr << "Missing chem_comp_bond category in data block " << db.getName() << std::endl;
// continue;
// }
// for (const auto& [atom_id_1, atom_id_2]: chem_comp_bond->rows<std::string,std::string>({"atom_id_1", "atom_id_2"}))
// {
// atomIDs.insert(atom_id_1);
// atomIDs.insert(atom_id_2);
// }
// compoundIDs.push_back({ db.getName() });
// }
// if (cif::VERBOSE)
// std::cout << "Number of unique atom names is " << atomIDs.size() << std::endl
// << "Number of unique residue names is " << compoundIDs.size() << std::endl;
// CompoundBondInfoFileHeader header = {};
// header.indexEntries = compoundIDs.size();
// header.atomEntries = atomIDs.size();
// outfile << header;
// for (auto atomID: atomIDs)
// outfile << atomID;
// auto dataOffset = outfile.tellp();
// std::vector<CompoundBondInfo> entries;
// entries.reserve(compoundIDs.size());
// std::map<atom_id_type, uint16_t> atomIDMap;
// for (auto& atomID: atomIDs)
// atomIDMap[atomID] = atomIDMap.size();
// for (auto& db: infile)
// {
// auto chem_comp_bond = db.get("chem_comp_bond");
// if (not chem_comp_bond)
// continue;
// std::set<uint16_t> bondedAtoms;
// for (const auto& [atom_id_1, atom_id_2]: chem_comp_bond->rows<std::string,std::string>({"atom_id_1", "atom_id_2"}))
// {
// bondedAtoms.insert(atomIDMap[atom_id_1]);
// bondedAtoms.insert(atomIDMap[atom_id_2]);
// }
// std::map<uint16_t, int32_t> bondedAtomMap;
// for (auto id: bondedAtoms)
// bondedAtomMap[id] = static_cast<int32_t>(bondedAtomMap.size());
// CompoundBondInfo info = {
// db.getName(),
// static_cast<uint32_t>(bondedAtomMap.size()),
// outfile.tellp() - dataOffset
// };
// entries.push_back(info);
// // An now first write the array of atom ID's in this compound
// for (uint16_t id: bondedAtoms)
// write(outfile, id);
// // And then the symmetric matrix with bonds
// size_t N = bondedAtoms.size();
// size_t M = (N * (N - 1)) / 2;
// size_t K = M / 8;
// if (M % 8)
// K += 1;
// std::vector<uint8_t> m(K);
// for (const auto& [atom_id_1, atom_id_2]: chem_comp_bond->rows<std::string,std::string>({"atom_id_1", "atom_id_2"}))
// {
// auto a = bondedAtomMap[atomIDMap[atom_id_1]];
// auto b = bondedAtomMap[atomIDMap[atom_id_2]];
// assert(a != b);
// assert((int)b < (int)N);
// if (a > b)
// std::swap(a, b);
// size_t ix = ((b - 1) * b) / 2 + a;
// assert(ix < M);
// auto Bix = ix / 8;
// auto bix = ix % 8;
// m[Bix] |= 1 << bix;
// }
// outfile.write(reinterpret_cast<char*>(m.data()), m.size());
// }
// header.dataSize = outfile.tellp() - dataOffset;
// std::sort(entries.begin(), entries.end(), [](CompoundBondInfo& a, CompoundBondInfo& b) IDType &operator=(const IDType &rhs)
// { {
// return a.id < b.id; id_n = rhs.id_n;
// }); return *this;
}
// for (auto& info: entries) IDType &operator=(const std::string &s)
// outfile << info; {
id_n = 0;
assert(s.length() <= 4);
if (s.length() > 4)
throw BondMapException("Atom ID '" + s + "' is too long");
std::copy(s.begin(), s.end(), id_s);
return *this;
}
// outfile.seekp(0); bool operator<(const IDType &rhs) const
// outfile << header; {
return id_n < rhs.id_n;
}
// // compress bool operator<=(const IDType &rhs) const
// outfile.close(); {
return id_n <= rhs.id_n;
}
// std::ifstream in(infofile.string() + ".tmp", std::ios::binary); bool operator==(const IDType &rhs) const
// std::ofstream out(infofile, std::ios::binary); {
return id_n == rhs.id_n;
}
// { bool operator!=(const IDType &rhs) const
// io::filtering_stream<io::output> os; {
// os.push(io::gzip_compressor()); return id_n != rhs.id_n;
// os.push(out); }
// io::copy(in, os);
// }
// in.close(); char id_s[4];
// out.close(); uint32_t id_n;
};
// fs::remove(infofile.string() + ".tmp"); static_assert(sizeof(IDType) == 4, "atom_id_type should be 4 bytes");
// } } // namespace
// -------------------------------------------------------------------- // --------------------------------------------------------------------
struct CompoundBondInfo struct CompoundBondInfo
{ {
IDType mID; IDType mID;
std::set<std::tuple<uint32_t,uint32_t>> mBonded; std::set<std::tuple<uint32_t, uint32_t>> mBonded;
bool bonded(uint32_t a1, uint32_t a2) const bool bonded(uint32_t a1, uint32_t a2) const
{ {
return mBonded.count({ a1, a2 }) > 0; return mBonded.count({a1, a2}) > 0;
} }
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -263,20 +119,18 @@ struct CompoundBondInfo ...@@ -263,20 +119,18 @@ struct CompoundBondInfo
class CompoundBondMap class CompoundBondMap
{ {
public: public:
static CompoundBondMap &instance() static CompoundBondMap &instance()
{ {
static std::unique_ptr<CompoundBondMap> s_instance(new CompoundBondMap); static std::unique_ptr<CompoundBondMap> s_instance(new CompoundBondMap);
return *s_instance; return *s_instance;
} }
bool bonded(const std::string& compoundID, const std::string& atomID1, const std::string& atomID2); bool bonded(const std::string &compoundID, const std::string &atomID1, const std::string &atomID2);
private: private:
CompoundBondMap() {} CompoundBondMap() {}
uint32_t getAtomID(const std::string& atomID) uint32_t getAtomID(const std::string &atomID)
{ {
IDType id(atomID); IDType id(atomID);
...@@ -290,16 +144,16 @@ class CompoundBondMap ...@@ -290,16 +144,16 @@ class CompoundBondMap
} }
else else
result = i->second; result = i->second;
return result; return result;
} }
std::map<IDType,uint32_t> mAtomIDIndex; std::map<IDType, uint32_t> mAtomIDIndex;
std::vector<CompoundBondInfo> mCompounds; std::vector<CompoundBondInfo> mCompounds;
std::mutex mMutex; std::mutex mMutex;
}; };
bool CompoundBondMap::bonded(const std::string &compoundID, const std::string& atomID1, const std::string& atomID2) bool CompoundBondMap::bonded(const std::string &compoundID, const std::string &atomID1, const std::string &atomID2)
{ {
std::lock_guard lock(mMutex); std::lock_guard lock(mMutex);
...@@ -310,32 +164,32 @@ bool CompoundBondMap::bonded(const std::string &compoundID, const std::string& a ...@@ -310,32 +164,32 @@ bool CompoundBondMap::bonded(const std::string &compoundID, const std::string& a
uint32_t a2 = getAtomID(atomID2); uint32_t a2 = getAtomID(atomID2);
if (a1 > a2) if (a1 > a2)
std::swap(a1, a2); std::swap(a1, a2);
for (auto &bi: mCompounds) for (auto &bi : mCompounds)
{ {
if (bi.mID != id) if (bi.mID != id)
continue; continue;
return bi.bonded(a1, a2); return bi.bonded(a1, a2);
} }
bool result = false; bool result = false;
// not found in our cache, calculate // not found in our cache, calculate
CompoundBondInfo bondInfo{ id }; CompoundBondInfo bondInfo{id};
auto compound = mmcif::CompoundFactory::instance().create(compoundID); auto compound = mmcif::CompoundFactory::instance().create(compoundID);
if (not compound) if (not compound)
std::cerr << "Missing compound bond info for " << compoundID << std::endl; std::cerr << "Missing compound bond info for " << compoundID << std::endl;
else else
{ {
for (auto &atom: compound->bonds()) for (auto &atom : compound->bonds())
{ {
uint32_t ca1 = getAtomID(atom.atomID[0]); uint32_t ca1 = getAtomID(atom.atomID[0]);
uint32_t ca2 = getAtomID(atom.atomID[1]); uint32_t ca2 = getAtomID(atom.atomID[1]);
if (ca1 > ca2) if (ca1 > ca2)
std::swap(ca1, ca2); std::swap(ca1, ca2);
bondInfo.mBonded.insert({ca1, ca2}); bondInfo.mBonded.insert({ca1, ca2});
result = result or (a1 == ca1 and a2 == ca2); result = result or (a1 == ca1 and a2 == ca2);
} }
...@@ -348,27 +202,27 @@ bool CompoundBondMap::bonded(const std::string &compoundID, const std::string& a ...@@ -348,27 +202,27 @@ bool CompoundBondMap::bonded(const std::string &compoundID, const std::string& a
// -------------------------------------------------------------------- // --------------------------------------------------------------------
BondMap::BondMap(const Structure& p) BondMap::BondMap(const Structure &p)
{ {
auto& compoundBondInfo = CompoundBondMap::instance(); auto &compoundBondInfo = CompoundBondMap::instance();
auto atoms = p.atoms(); auto atoms = p.atoms();
dim = uint32_t(atoms.size()); dim = uint32_t(atoms.size());
// bond = std::vector<bool>(dim * (dim - 1), false); // bond = std::vector<bool>(dim * (dim - 1), false);
for (auto& atom: atoms) for (auto &atom : atoms)
index[atom.id()] = uint32_t(index.size()); index[atom.id()] = uint32_t(index.size());
auto bindAtoms = [this](const std::string& a, const std::string& b) auto bindAtoms = [this](const std::string &a, const std::string &b)
{ {
uint32_t ixa = index[a]; uint32_t ixa = index[a];
uint32_t ixb = index[b]; uint32_t ixb = index[b];
bond.insert(key(ixa, ixb)); bond.insert(key(ixa, ixb));
}; };
auto linkAtoms = [this,&bindAtoms](const std::string& a, const std::string& b) auto linkAtoms = [this, &bindAtoms](const std::string &a, const std::string &b)
{ {
bindAtoms(a, b); bindAtoms(a, b);
...@@ -376,20 +230,20 @@ BondMap::BondMap(const Structure& p) ...@@ -376,20 +230,20 @@ BondMap::BondMap(const Structure& p)
link[b].insert(a); link[b].insert(a);
}; };
cif::Datablock& db = p.getFile().data(); cif::Datablock &db = p.getFile().data();
// collect all compounds first // collect all compounds first
std::set<std::string> compounds; std::set<std::string> compounds;
for (auto c: db["chem_comp"]) for (auto c : db["chem_comp"])
compounds.insert(c["id"].as<std::string>()); compounds.insert(c["id"].as<std::string>());
// make sure we also have all residues in the polyseq // make sure we also have all residues in the polyseq
for (auto m: db["entity_poly_seq"]) for (auto m : db["entity_poly_seq"])
{ {
std::string c = m["mon_id"].as<std::string>(); std::string c = m["mon_id"].as<std::string>();
if (compounds.count(c)) if (compounds.count(c))
continue; continue;
if (cif::VERBOSE > 1) if (cif::VERBOSE > 1)
std::cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << std::endl; std::cerr << "Warning: mon_id " << c << " is missing in the chem_comp category" << std::endl;
compounds.insert(c); compounds.insert(c);
...@@ -398,59 +252,59 @@ BondMap::BondMap(const Structure& p) ...@@ -398,59 +252,59 @@ BondMap::BondMap(const Structure& p)
cif::Progress progress(compounds.size(), "Creating bond map"); cif::Progress progress(compounds.size(), "Creating bond map");
// some helper indices to speed things up a bit // some helper indices to speed things up a bit
std::map<std::tuple<std::string,int,std::string>,std::string> atomMapByAsymSeqAndAtom; std::map<std::tuple<std::string, int, std::string>, std::string> atomMapByAsymSeqAndAtom;
for (auto& a: p.atoms()) for (auto &a : p.atoms())
{ {
auto key = make_tuple(a.labelAsymID(), a.labelSeqID(), a.labelAtomID()); auto key = make_tuple(a.labelAsymID(), a.labelSeqID(), a.labelAtomID());
atomMapByAsymSeqAndAtom[key] = a.id(); atomMapByAsymSeqAndAtom[key] = a.id();
} }
// first link all residues in a polyseq // first link all residues in a polyseq
std::string lastAsymID; std::string lastAsymID;
int lastSeqID = 0; int lastSeqID = 0;
for (auto r: db["pdbx_poly_seq_scheme"]) for (auto r : db["pdbx_poly_seq_scheme"])
{ {
std::string asymID; std::string asymID;
int seqID; int seqID;
cif::tie(asymID, seqID) = r.get("asym_id", "seq_id"); cif::tie(asymID, seqID) = r.get("asym_id", "seq_id");
if (asymID != lastAsymID) // first in a new sequece if (asymID != lastAsymID) // first in a new sequece
{ {
lastAsymID = asymID; lastAsymID = asymID;
lastSeqID = seqID; lastSeqID = seqID;
continue; continue;
} }
auto c = atomMapByAsymSeqAndAtom[make_tuple(asymID, lastSeqID, "C")]; auto c = atomMapByAsymSeqAndAtom[make_tuple(asymID, lastSeqID, "C")];
auto n = atomMapByAsymSeqAndAtom[make_tuple(asymID, seqID, "N")]; auto n = atomMapByAsymSeqAndAtom[make_tuple(asymID, seqID, "N")];
if (not (c.empty() or n.empty())) if (not(c.empty() or n.empty()))
bindAtoms(c, n); bindAtoms(c, n);
lastSeqID = seqID; lastSeqID = seqID;
} }
for (auto l: db["struct_conn"]) for (auto l : db["struct_conn"])
{ {
std::string asym1, asym2, atomId1, atomId2; std::string asym1, asym2, atomId1, atomId2;
int seqId1 = 0, seqId2 = 0; int seqId1 = 0, seqId2 = 0;
cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) = cif::tie(asym1, asym2, atomId1, atomId2, seqId1, seqId2) =
l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id", l.get("ptnr1_label_asym_id", "ptnr2_label_asym_id",
"ptnr1_label_atom_id", "ptnr2_label_atom_id", "ptnr1_label_atom_id", "ptnr2_label_atom_id",
"ptnr1_label_seq_id", "ptnr2_label_seq_id"); "ptnr1_label_seq_id", "ptnr2_label_seq_id");
std::string a = atomMapByAsymSeqAndAtom[make_tuple(asym1, seqId1, atomId1)]; std::string a = atomMapByAsymSeqAndAtom[make_tuple(asym1, seqId1, atomId1)];
std::string b = atomMapByAsymSeqAndAtom[make_tuple(asym2, seqId2, atomId2)]; std::string b = atomMapByAsymSeqAndAtom[make_tuple(asym2, seqId2, atomId2)];
if (not (a.empty() or b.empty())) if (not(a.empty() or b.empty()))
linkAtoms(a, b); linkAtoms(a, b);
} }
// then link all atoms in the compounds // then link all atoms in the compounds
for (auto c: compounds) for (auto c : compounds)
{ {
if (c == "HOH" or c == "H2O" or c == "WAT") if (c == "HOH" or c == "H2O" or c == "WAT")
{ {
...@@ -459,7 +313,7 @@ BondMap::BondMap(const Structure& p) ...@@ -459,7 +313,7 @@ BondMap::BondMap(const Structure& p)
continue; continue;
} }
auto bonded = [c, &compoundBondInfo](const Atom& a, const Atom& b) auto bonded = [c, &compoundBondInfo](const Atom &a, const Atom &b)
{ {
auto label_a = a.labelAtomID(); auto label_a = a.labelAtomID();
auto label_b = b.labelAtomID(); auto label_b = b.labelAtomID();
...@@ -468,16 +322,17 @@ BondMap::BondMap(const Structure& p) ...@@ -468,16 +322,17 @@ BondMap::BondMap(const Structure& p)
}; };
// loop over poly_seq_scheme // loop over poly_seq_scheme
for (auto r: db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c)) for (auto r : db["pdbx_poly_seq_scheme"].find(cif::Key("mon_id") == c))
{ {
std::string asymID; std::string asymID;
int seqID; int seqID;
cif::tie(asymID, seqID) = r.get("asym_id", "seq_id"); cif::tie(asymID, seqID) = r.get("asym_id", "seq_id");
std::vector<Atom> rAtoms; std::vector<Atom> rAtoms;
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms), copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
[&](auto& a) { return a.labelAsymID() == asymID and a.labelSeqID() == seqID; }); [&](auto &a)
{ return a.labelAsymID() == asymID and a.labelSeqID() == seqID; });
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i) for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
{ {
for (uint32_t j = i + 1; j < rAtoms.size(); ++j) for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
...@@ -489,15 +344,16 @@ BondMap::BondMap(const Structure& p) ...@@ -489,15 +344,16 @@ BondMap::BondMap(const Structure& p)
} }
// loop over pdbx_nonpoly_scheme // loop over pdbx_nonpoly_scheme
for (auto r: db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c)) for (auto r : db["pdbx_nonpoly_scheme"].find(cif::Key("mon_id") == c))
{ {
std::string asymID; std::string asymID;
cif::tie(asymID) = r.get("asym_id"); cif::tie(asymID) = r.get("asym_id");
std::vector<Atom> rAtoms; std::vector<Atom> rAtoms;
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms), copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
[&](auto& a) { return a.labelAsymID() == asymID; }); [&](auto &a)
{ return a.labelAsymID() == asymID; });
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i) for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
{ {
for (uint32_t j = i + 1; j < rAtoms.size(); ++j) for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
...@@ -506,7 +362,7 @@ BondMap::BondMap(const Structure& p) ...@@ -506,7 +362,7 @@ BondMap::BondMap(const Structure& p)
{ {
uint32_t ixa = index[rAtoms[i].id()]; uint32_t ixa = index[rAtoms[i].id()];
uint32_t ixb = index[rAtoms[j].id()]; uint32_t ixb = index[rAtoms[j].id()];
bond.insert(key(ixa, ixb)); bond.insert(key(ixa, ixb));
} }
} }
...@@ -514,15 +370,16 @@ BondMap::BondMap(const Structure& p) ...@@ -514,15 +370,16 @@ BondMap::BondMap(const Structure& p)
} }
// loop over pdbx_branch_scheme // loop over pdbx_branch_scheme
for (auto r: db["pdbx_branch_scheme"].find(cif::Key("mon_id") == c)) for (auto r : db["pdbx_branch_scheme"].find(cif::Key("mon_id") == c))
{ {
std::string asymID; std::string asymID;
cif::tie(asymID) = r.get("asym_id"); cif::tie(asymID) = r.get("asym_id");
std::vector<Atom> rAtoms; std::vector<Atom> rAtoms;
copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms), copy_if(atoms.begin(), atoms.end(), back_inserter(rAtoms),
[&](auto& a) { return a.labelAsymID() == asymID; }); [&](auto &a)
{ return a.labelAsymID() == asymID; });
for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i) for (uint32_t i = 0; i + 1 < rAtoms.size(); ++i)
{ {
for (uint32_t j = i + 1; j < rAtoms.size(); ++j) for (uint32_t j = i + 1; j < rAtoms.size(); ++j)
...@@ -531,31 +388,31 @@ BondMap::BondMap(const Structure& p) ...@@ -531,31 +388,31 @@ BondMap::BondMap(const Structure& p)
{ {
uint32_t ixa = index[rAtoms[i].id()]; uint32_t ixa = index[rAtoms[i].id()];
uint32_t ixb = index[rAtoms[j].id()]; uint32_t ixb = index[rAtoms[j].id()];
bond.insert(key(ixa, ixb)); bond.insert(key(ixa, ixb));
} }
} }
} }
} }
} }
// start by creating an index for single bonds // start by creating an index for single bonds
std::multimap<uint32_t,uint32_t> b1_2; std::multimap<uint32_t, uint32_t> b1_2;
for (auto& bk: bond) for (auto &bk : bond)
{ {
uint32_t a, b; uint32_t a, b;
std::tie(a, b) = dekey(bk); std::tie(a, b) = dekey(bk);
b1_2.insert({ a, b }); b1_2.insert({a, b});
b1_2.insert({ b, a }); b1_2.insert({b, a});
} }
std::multimap<uint32_t,uint32_t> b1_3; std::multimap<uint32_t, uint32_t> b1_3;
for (uint32_t i = 0; i < dim; ++i) for (uint32_t i = 0; i < dim; ++i)
{ {
auto a = b1_2.equal_range(i); auto a = b1_2.equal_range(i);
std::vector<uint32_t> s; std::vector<uint32_t> s;
for (auto j = a.first; j != a.second; ++j) for (auto j = a.first; j != a.second; ++j)
s.push_back(j->second); s.push_back(j->second);
...@@ -566,12 +423,12 @@ BondMap::BondMap(const Structure& p) ...@@ -566,12 +423,12 @@ BondMap::BondMap(const Structure& p)
{ {
uint32_t x = s[si1]; uint32_t x = s[si1];
uint32_t y = s[si2]; uint32_t y = s[si2];
if (isBonded(x, y)) if (isBonded(x, y))
continue; continue;
b1_3.insert({ x, y }); b1_3.insert({x, y});
b1_3.insert({ y, x }); b1_3.insert({y, x});
} }
} }
} }
...@@ -580,48 +437,48 @@ BondMap::BondMap(const Structure& p) ...@@ -580,48 +437,48 @@ BondMap::BondMap(const Structure& p)
{ {
auto a1 = b1_2.equal_range(i); auto a1 = b1_2.equal_range(i);
auto a2 = b1_3.equal_range(i); auto a2 = b1_3.equal_range(i);
for (auto ai1 = a1.first; ai1 != a1.second; ++ai1) for (auto ai1 = a1.first; ai1 != a1.second; ++ai1)
{ {
for (auto ai2 = a2.first; ai2 != a2.second; ++ai2) for (auto ai2 = a2.first; ai2 != a2.second; ++ai2)
{ {
uint32_t b1 = ai1->second; uint32_t b1 = ai1->second;
uint32_t b2 = ai2->second; uint32_t b2 = ai2->second;
if (isBonded(b1, b2)) if (isBonded(b1, b2))
continue; continue;
bond_1_4.insert(key(b1, b2)); bond_1_4.insert(key(b1, b2));
} }
} }
} }
} }
std::vector<std::string> BondMap::linked(const Atom& a) const std::vector<std::string> BondMap::linked(const Atom &a) const
{ {
auto i = link.find(a.id()); auto i = link.find(a.id());
std::vector<std::string> result; std::vector<std::string> result;
if (i != link.end()) if (i != link.end())
result = std::vector<std::string>(i->second.begin(), i->second.end()); result = std::vector<std::string>(i->second.begin(), i->second.end());
return result; return result;
} }
std::vector<std::string> BondMap::atomIDsForCompound(const std::string& compoundID) std::vector<std::string> BondMap::atomIDsForCompound(const std::string &compoundID)
{ {
std::vector<std::string> result; std::vector<std::string> result;
auto* compound = mmcif::CompoundFactory::instance().create(compoundID); auto *compound = mmcif::CompoundFactory::instance().create(compoundID);
if (compound == nullptr) if (compound == nullptr)
throw BondMapException("Missing bond information for compound " + compoundID); throw BondMapException("Missing bond information for compound " + compoundID);
for (auto& compAtom: compound->atoms()) for (auto &compAtom : compound->atoms())
result.push_back(compAtom.id); result.push_back(compAtom.id);
return result; return result;
} }
} } // namespace mmcif
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <stack> #include <stack>
#include <tuple> #include <tuple>
#include <unordered_map> #include <unordered_map>
#include <shared_mutex>
#include <filesystem> #include <filesystem>
...@@ -351,7 +352,7 @@ namespace detail ...@@ -351,7 +352,7 @@ namespace detail
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Datablock implementation // Datablock implementation
Datablock::Datablock(const std::string &name) Datablock::Datablock(const std::string_view name)
: mName(name) : mName(name)
, mValidator(nullptr) , mValidator(nullptr)
, mNext(nullptr) , mNext(nullptr)
...@@ -363,70 +364,81 @@ Datablock::~Datablock() ...@@ -363,70 +364,81 @@ Datablock::~Datablock()
delete mNext; delete mNext;
} }
std::string Datablock::firstItem(const std::string &tag) const auto Datablock::emplace(std::string_view name) -> std::tuple<iterator, bool>
{ {
std::string result; // LRU code
std::string catName, itemName; std::shared_lock lock(mLock);
std::tie(catName, itemName) = splitTagName(tag);
for (auto &cat : mCategories) bool isNew = true;
auto i = begin();
while (i != end())
{ {
if (iequals(cat.name(), catName)) if (iequals(name, i->name()))
{ {
for (auto row : cat) isNew = false;
if (i != begin())
{ {
result = row[itemName].as<std::string>(); auto n = std::next(i);
break; mCategories.splice(begin(), mCategories, i, n);
} }
break; break;
} }
}
return result; ++i;
} }
auto Datablock::emplace(const std::string &name) -> std::tuple<iterator, bool>
{
bool isNew = false;
iterator i = find_if(begin(), end(), [name](const Category &cat) -> bool
{ return iequals(cat.name(), name); });
if (i == end()) if (isNew)
{ {
isNew = true; mCategories.emplace(begin(), *this, std::string(name), mValidator);
i = mCategories.emplace(end(), *this, name, mValidator);
for (auto &cat : mCategories)
cat.updateLinks();
} }
return std::make_tuple(i, isNew); return std::make_tuple(begin(), isNew);
} }
Category &Datablock::operator[](const std::string &name) Category &Datablock::operator[](std::string_view name)
{ {
iterator i; iterator i;
std::tie(i, std::ignore) = emplace(name); std::tie(i, std::ignore) = emplace(name);
return *i; return *i;
} }
Category *Datablock::get(const std::string &name) Category *Datablock::get(std::string_view name)
{ {
auto i = find_if(begin(), end(), [name](const Category &cat) -> bool std::shared_lock lock(mLock);
{ return iequals(cat.name(), name); });
for (auto &cat : mCategories)
{
if (iequals(cat.name(), name))
return &cat;
}
return i == end() ? nullptr : &*i; return nullptr;
} }
const Category *Datablock::get(const std::string &name) const const Category *Datablock::get(std::string_view name) const
{ {
auto i = find_if(begin(), end(), [name](const Category &cat) -> bool std::shared_lock lock(mLock);
{ return iequals(cat.name(), name); });
return i == end() ? nullptr : &*i; for (auto &cat : mCategories)
{
if (iequals(cat.name(), name))
return &cat;
}
return nullptr;
} }
bool Datablock::isValid() bool Datablock::isValid()
{ {
std::shared_lock lock(mLock);
if (mValidator == nullptr) if (mValidator == nullptr)
throw std::runtime_error("Validator not specified"); throw std::runtime_error("Validator not specified");
...@@ -438,20 +450,26 @@ bool Datablock::isValid() ...@@ -438,20 +450,26 @@ bool Datablock::isValid()
void Datablock::validateLinks() const void Datablock::validateLinks() const
{ {
std::shared_lock lock(mLock);
for (auto &cat : *this) for (auto &cat : *this)
cat.validateLinks(); cat.validateLinks();
} }
void Datablock::setValidator(Validator *v) void Datablock::setValidator(const Validator *v)
{ {
std::shared_lock lock(mLock);
mValidator = v; mValidator = v;
for (auto &cat : *this) for (auto &cat : *this)
cat.setValidator(v); cat.setValidator(v);
} }
void Datablock::add_software(const std::string &name, const std::string &classification, const std::string &versionNr, const std::string &versionDate) void Datablock::add_software(const std::string_view name, const std::string &classification, const std::string &versionNr, const std::string &versionDate)
{ {
std::shared_lock lock(mLock);
Category &cat = operator[]("software"); Category &cat = operator[]("software");
auto ordNr = cat.size() + 1; auto ordNr = cat.size() + 1;
// TODO: should we check this ordinal number??? // TODO: should we check this ordinal number???
...@@ -465,12 +483,16 @@ void Datablock::add_software(const std::string &name, const std::string &classif ...@@ -465,12 +483,16 @@ void Datablock::add_software(const std::string &name, const std::string &classif
void Datablock::getTagOrder(std::vector<std::string> &tags) const void Datablock::getTagOrder(std::vector<std::string> &tags) const
{ {
std::shared_lock lock(mLock);
for (auto &cat : *this) for (auto &cat : *this)
cat.getTagOrder(tags); cat.getTagOrder(tags);
} }
void Datablock::write(std::ostream &os) void Datablock::write(std::ostream &os)
{ {
std::shared_lock lock(mLock);
os << "data_" << mName << std::endl os << "data_" << mName << std::endl
<< "# " << std::endl; << "# " << std::endl;
...@@ -505,6 +527,8 @@ void Datablock::write(std::ostream &os) ...@@ -505,6 +527,8 @@ void Datablock::write(std::ostream &os)
void Datablock::write(std::ostream &os, const std::vector<std::string> &order) void Datablock::write(std::ostream &os, const std::vector<std::string> &order)
{ {
std::shared_lock lock(mLock);
os << "data_" << mName << std::endl os << "data_" << mName << std::endl
<< "# " << std::endl; << "# " << std::endl;
...@@ -580,6 +604,11 @@ void Datablock::write(std::ostream &os, const std::vector<std::string> &order) ...@@ -580,6 +604,11 @@ void Datablock::write(std::ostream &os, const std::vector<std::string> &order)
bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB) bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
{ {
bool result = true;
std::shared_lock lockA(dbA.mLock);
std::shared_lock lockB(dbB.mLock);
std::vector<std::string> catA, catB; std::vector<std::string> catA, catB;
for (auto &cat : dbA) for (auto &cat : dbA)
...@@ -605,14 +634,59 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB) ...@@ -605,14 +634,59 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
while (catA_i != catA.end() and catB_i != catB.end()) while (catA_i != catA.end() and catB_i != catB.end())
{ {
if (not iequals(*catA_i, *catB_i)) std::string nA = *catA_i;
return false; ba::to_lower(nA);
std::string nB = *catB_i;
ba::to_lower(nB);
int d = nA.compare(nB);
if (d > 0)
{
auto cat = dbB.get(*catB_i);
if (cat == nullptr)
missingA.push_back(*catB_i);
++catB_i;
}
else if (d < 0)
{
auto cat = dbA.get(*catA_i);
if (cat == nullptr)
missingB.push_back(*catA_i);
++catA_i, ++catB_i; ++catA_i;
}
else
++catA_i, ++catB_i;
} }
while (catA_i != catA.end())
missingB.push_back(*catA_i++);
if (catA_i != catA.end() or catB_i != catB.end()) while (catB_i != catB.end())
return false; missingA.push_back(*catB_i++);
if (not (missingA.empty() and missingB.empty()))
{
if (cif::VERBOSE > 1)
{
std::cerr << "compare of datablocks failed" << std::endl;
if (not missingA.empty())
std::cerr << "Categories missing in A: " << ba::join(missingA, ", ") << std::endl
<< std::endl;
if (not missingB.empty())
std::cerr << "Categories missing in B: " << ba::join(missingB, ", ") << std::endl
<< std::endl;
result = false;
}
else
return false;
}
// Second loop, now compare category values // Second loop, now compare category values
catA_i = catA.begin(), catB_i = catB.begin(); catA_i = catA.begin(), catB_i = catB.begin();
...@@ -633,13 +707,21 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB) ...@@ -633,13 +707,21 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
else else
{ {
if (not (*dbA.get(*catA_i) == *dbB.get(*catB_i))) if (not (*dbA.get(*catA_i) == *dbB.get(*catB_i)))
return false; {
if (cif::VERBOSE > 1)
{
std::cerr << "Compare of datablocks failed due to unequal values in category " << *catA_i << std::endl;
result = false;
}
else
return false;
}
++catA_i; ++catA_i;
++catB_i; ++catB_i;
} }
} }
return true; return result;
} }
std::ostream& operator<<(std::ostream &os, const Datablock &data) std::ostream& operator<<(std::ostream &os, const Datablock &data)
...@@ -1311,7 +1393,7 @@ RowSet &RowSet::orderBy(std::initializer_list<std::string> items) ...@@ -1311,7 +1393,7 @@ RowSet &RowSet::orderBy(std::initializer_list<std::string> items)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Category::Category(Datablock &db, const std::string &name, Validator *Validator) Category::Category(Datablock &db, const std::string_view name, const Validator *Validator)
: mDb(db) : mDb(db)
, mName(name) , mName(name)
, mValidator(Validator) , mValidator(Validator)
...@@ -1346,7 +1428,7 @@ Category::~Category() ...@@ -1346,7 +1428,7 @@ Category::~Category()
delete mIndex; delete mIndex;
} }
void Category::setValidator(Validator *v) void Category::setValidator(const Validator *v)
{ {
mValidator = v; mValidator = v;
...@@ -1371,14 +1453,41 @@ void Category::setValidator(Validator *v) ...@@ -1371,14 +1453,41 @@ void Category::setValidator(Validator *v)
} }
else else
mCatValidator = nullptr; mCatValidator = nullptr;
updateLinks();
}
void Category::updateLinks()
{
mChildLinks.clear();
mParentLinks.clear();
if (mValidator != nullptr)
{
for (auto link : mValidator->getLinksForParent(mName))
{
auto childCat = mDb.get(link->mChildCategory);
if (childCat == nullptr)
continue;
mChildLinks.push_back({ childCat, link });
}
for (auto link : mValidator->getLinksForChild(mName))
{
auto parentCat = mDb.get(link->mParentCategory);
if (parentCat == nullptr)
continue;
mParentLinks.push_back({ parentCat, link });
}
}
} }
bool Category::hasColumn(const std::string &name) const bool Category::hasColumn(std::string_view name) const
{ {
return getColumnIndex(name) < mColumns.size(); return getColumnIndex(name) < mColumns.size();
} }
size_t Category::getColumnIndex(const std::string &name) const size_t Category::getColumnIndex(std::string_view name) const
{ {
size_t result; size_t result;
...@@ -1392,7 +1501,7 @@ size_t Category::getColumnIndex(const std::string &name) const ...@@ -1392,7 +1501,7 @@ size_t Category::getColumnIndex(const std::string &name) const
{ {
auto iv = mCatValidator->getValidatorForItem(name); auto iv = mCatValidator->getValidatorForItem(name);
if (iv == nullptr) if (iv == nullptr)
std::cerr << "Invalid name used '" + name + "' is not a known column in " + mName << std::endl; std::cerr << "Invalid name used '" << name << "' is not a known column in " + mName << std::endl;
} }
return result; return result;
...@@ -1411,8 +1520,10 @@ std::vector<std::string> Category::getColumnNames() const ...@@ -1411,8 +1520,10 @@ std::vector<std::string> Category::getColumnNames() const
return result; return result;
} }
size_t Category::addColumn(const std::string &name) size_t Category::addColumn(std::string_view name)
{ {
using namespace std::literals;
size_t result = getColumnIndex(name); size_t result = getColumnIndex(name);
if (result == mColumns.size()) if (result == mColumns.size())
...@@ -1423,10 +1534,10 @@ size_t Category::addColumn(const std::string &name) ...@@ -1423,10 +1534,10 @@ size_t Category::addColumn(const std::string &name)
{ {
itemValidator = mCatValidator->getValidatorForItem(name); itemValidator = mCatValidator->getValidatorForItem(name);
if (itemValidator == nullptr) if (itemValidator == nullptr)
mValidator->reportError("tag " + name + " not allowed in Category " + mName, false); mValidator->reportError("tag " + std::string(name) + " not allowed in Category " + mName, false);
} }
mColumns.push_back({name, itemValidator}); mColumns.push_back(ItemColumn{std::string(name), itemValidator});
} }
return result; return result;
...@@ -1814,12 +1925,8 @@ auto Category::erase(iterator pos) -> iterator ...@@ -1814,12 +1925,8 @@ auto Category::erase(iterator pos) -> iterator
if (mValidator != nullptr) if (mValidator != nullptr)
{ {
for (auto &link : mValidator->getLinksForParent(mName)) for (auto &&[childCat, link] : mChildLinks)
{ {
auto childCat = mDb.get(link->mChildCategory);
if (childCat == nullptr)
continue;
Condition cond; Condition cond;
for (size_t ix = 0; ix < link->mParentKeys.size(); ++ix) for (size_t ix = 0; ix < link->mParentKeys.size(); ++ix)
...@@ -1957,12 +2064,8 @@ bool Category::isOrphan(Row r) ...@@ -1957,12 +2064,8 @@ bool Category::isOrphan(Row r)
return false; return false;
bool isOrphan = true; bool isOrphan = true;
for (auto &link : mValidator->getLinksForChild(mName)) for (auto &&[parentCat, link] : mParentLinks)
{ {
auto parentCat = mDb.get(link->mParentCategory);
if (parentCat == nullptr)
continue;
Condition cond; Condition cond;
for (size_t ix = 0; ix < link->mChildKeys.size(); ++ix) for (size_t ix = 0; ix < link->mChildKeys.size(); ++ix)
{ {
...@@ -1993,12 +2096,8 @@ bool Category::hasChildren(Row r) const ...@@ -1993,12 +2096,8 @@ bool Category::hasChildren(Row r) const
bool result = false; bool result = false;
for (auto &link : mValidator->getLinksForParent(mName)) for (auto &&[childCat, link] : mChildLinks)
{ {
auto childCat = mDb.get(link->mChildCategory);
if (childCat == nullptr)
continue;
Condition cond; Condition cond;
for (size_t ix = 0; ix < link->mParentKeys.size(); ++ix) for (size_t ix = 0; ix < link->mParentKeys.size(); ++ix)
...@@ -2024,12 +2123,8 @@ bool Category::hasParents(Row r) const ...@@ -2024,12 +2123,8 @@ bool Category::hasParents(Row r) const
bool result = false; bool result = false;
for (auto &link : mValidator->getLinksForChild(mName)) for (auto &&[parentCat, link] : mParentLinks)
{ {
auto parentCat = mDb.get(link->mParentCategory);
if (parentCat == nullptr)
continue;
Condition cond; Condition cond;
for (size_t ix = 0; ix < link->mChildKeys.size(); ++ix) for (size_t ix = 0; ix < link->mChildKeys.size(); ++ix)
...@@ -2238,23 +2333,17 @@ bool Category::isValid() ...@@ -2238,23 +2333,17 @@ bool Category::isValid()
void Category::validateLinks() const void Category::validateLinks() const
{ {
auto &validator = getValidator(); for (auto &&[parentCat, link] : mParentLinks)
for (auto linkValidator : validator.getLinksForChild(mName))
{ {
auto parent = mDb.get(linkValidator->mParentCategory);
if (parent == nullptr)
continue;
size_t missing = 0; size_t missing = 0;
for (auto r : *this) for (auto r : *this)
if (not hasParent(r, *parent, *linkValidator)) if (not hasParent(r, *parentCat, *link))
++missing; ++missing;
if (missing) if (missing)
{ {
std::cerr << "Links for " << linkValidator->mLinkGroupLabel << " are incomplete" << std::endl std::cerr << "Links for " << link->mLinkGroupLabel << " are incomplete" << std::endl
<< " There are " << missing << " items in " << mName << " that don't have matching parent items in " << parent->mName << std::endl; << " There are " << missing << " items in " << mName << " that don't have matching parent items in " << parentCat->mName << std::endl;
} }
} }
} }
...@@ -2320,7 +2409,9 @@ std::set<size_t> Category::keyFieldsByIndex() const ...@@ -2320,7 +2409,9 @@ std::set<size_t> Category::keyFieldsByIndex() const
bool operator==(const Category &a, const Category &b) bool operator==(const Category &a, const Category &b)
{ {
using namespace std::placeholders; using namespace std::placeholders;
bool result = true;
// set<std::string> tagsA(a.fields()), tagsB(b.fields()); // set<std::string> tagsA(a.fields()), tagsB(b.fields());
// //
// if (tagsA != tagsB) // if (tagsA != tagsB)
...@@ -2354,7 +2445,7 @@ bool operator==(const Category &a, const Category &b) ...@@ -2354,7 +2445,7 @@ bool operator==(const Category &a, const Category &b)
// a.reorderByIndex(); // a.reorderByIndex();
// b.reorderByIndex(); // b.reorderByIndex();
auto rowEqual = [&](const cif::Row& a, const cif::Row& b) auto rowEqual = [&](const cif::Row& ra, const cif::Row& rb)
{ {
int d = 0; int d = 0;
...@@ -2365,10 +2456,14 @@ bool operator==(const Category &a, const Category &b) ...@@ -2365,10 +2456,14 @@ bool operator==(const Category &a, const Category &b)
std::tie(tag, compare) = tags[kix]; std::tie(tag, compare) = tags[kix];
d = compare(a[tag].c_str(), b[tag].c_str()); d = compare(ra[tag].c_str(), rb[tag].c_str());
if (d != 0) if (d != 0)
{
if (cif::VERBOSE > 1)
std::cerr << "Values in _" << a.name() << '.' << tag << " are not equal: '" << ra[tag].c_str() << "' != '" << rb[tag].c_str() << '\'' << std::endl;
break; break;
}
} }
return d == 0; return d == 0;
...@@ -2378,12 +2473,26 @@ bool operator==(const Category &a, const Category &b) ...@@ -2378,12 +2473,26 @@ bool operator==(const Category &a, const Category &b)
while (ai != a.end() or bi != b.end()) while (ai != a.end() or bi != b.end())
{ {
if (ai == a.end() or bi == b.end()) if (ai == a.end() or bi == b.end())
return false; {
if (cif::VERBOSE > 1)
{
std::cerr << "Unequal number of rows in " << a.name() << std::endl;
result = false;
break;
}
else
return false;
}
cif::Row ra = *ai, rb = *bi; cif::Row ra = *ai, rb = *bi;
if (not rowEqual(ra, rb)) if (not rowEqual(ra, rb))
return false; {
if (cif::VERBOSE > 1)
result = false;
else
return false;
}
std::vector<std::string> missingA, missingB, different; std::vector<std::string> missingA, missingB, different;
...@@ -2400,14 +2509,22 @@ bool operator==(const Category &a, const Category &b) ...@@ -2400,14 +2509,22 @@ bool operator==(const Category &a, const Category &b)
const char* tb = rb[tag].c_str(); if (strcmp(tb, ".") == 0 or strcmp(tb, "?") == 0) tb = ""; const char* tb = rb[tag].c_str(); if (strcmp(tb, ".") == 0 or strcmp(tb, "?") == 0) tb = "";
if (compare(ta, tb) != 0) if (compare(ta, tb) != 0)
return false; {
if (cif::VERBOSE > 1)
{
std::cerr << "Values in _" << a.name() << '.' << tag << " are not equal: '" << ta << "' != '" << tb << '\'' << std::endl;
result = false;
}
else
return false;
}
} }
++ai; ++ai;
++bi; ++bi;
} }
return true; return result;
} }
// auto Category::iterator::operator++() -> iterator& // auto Category::iterator::operator++() -> iterator&
...@@ -2695,17 +2812,10 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st ...@@ -2695,17 +2812,10 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
row.assign(colIx, value, true); row.assign(colIx, value, true);
// see if we need to update any child categories that depend on this value // see if we need to update any child categories that depend on this value
auto &validator = getValidator();
auto &db = mDb;
for (auto parent : rows) for (auto parent : rows)
{ {
for (auto linked : validator.getLinksForParent(mName)) for (auto &&[childCat, linked] : mChildLinks)
{ {
auto childCat = db.get(linked->mChildCategory);
if (childCat == nullptr)
continue;
if (std::find(linked->mParentKeys.begin(), linked->mParentKeys.end(), tag) == linked->mParentKeys.end()) if (std::find(linked->mParentKeys.begin(), linked->mParentKeys.end(), tag) == linked->mParentKeys.end())
continue; continue;
...@@ -2862,18 +2972,8 @@ void Row::assign(const std::vector<Item> &values) ...@@ -2862,18 +2972,8 @@ void Row::assign(const std::vector<Item> &values)
// auto iv = col.mValidator; // auto iv = col.mValidator;
if (mCascade) if (mCascade)
{ {
auto &validator = cat->getValidator(); for (auto &&[childCat, linked] : cat->mChildLinks)
auto &db = cat->db();
for (auto linked : validator.getLinksForParent(cat->mName))
{ {
auto childCat = db.get(linked->mChildCategory);
if (childCat == nullptr)
continue;
// if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
// continue;
Condition cond; Condition cond;
std::string childTag; std::string childTag;
...@@ -2909,7 +3009,7 @@ void Row::assign(const Item &value, bool skipUpdateLinked) ...@@ -2909,7 +3009,7 @@ void Row::assign(const Item &value, bool skipUpdateLinked)
assign(value.name(), value.value(), skipUpdateLinked); assign(value.name(), value.value(), skipUpdateLinked);
} }
void Row::assign(const std::string &name, const std::string &value, bool skipUpdateLinked) void Row::assign(std::string_view name, const std::string &value, bool skipUpdateLinked)
{ {
try try
{ {
...@@ -3014,15 +3114,8 @@ void Row::assign(size_t column, const std::string &value, bool skipUpdateLinked) ...@@ -3014,15 +3114,8 @@ void Row::assign(size_t column, const std::string &value, bool skipUpdateLinked)
auto iv = col.mValidator; auto iv = col.mValidator;
if (not skipUpdateLinked and iv != nullptr and mCascade) if (not skipUpdateLinked and iv != nullptr and mCascade)
{ {
auto &validator = cat->getValidator(); for (auto &&[childCat, linked] : cat->mChildLinks)
auto &db = cat->db();
for (auto linked : validator.getLinksForParent(cat->mName))
{ {
auto childCat = db.get(linked->mChildCategory);
if (childCat == nullptr)
continue;
if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end()) if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
continue; continue;
...@@ -3201,18 +3294,13 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b) ...@@ -3201,18 +3294,13 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
auto parentColName = cat->getColumnName(cix); auto parentColName = cat->getColumnName(cix);
// see if we need to update any child categories that depend on these values // see if we need to update any child categories that depend on these values
auto &validator = cat->getValidator();
auto parentCatValidator = cat->getCatValidator(); auto parentCatValidator = cat->getCatValidator();
for (auto &link : validator.getLinksForParent(cat->mName)) for (auto &&[childCat, link] : cat->mChildLinks)
{ {
if (find(link->mParentKeys.begin(), link->mParentKeys.end(), parentColName) == link->mParentKeys.end()) if (find(link->mParentKeys.begin(), link->mParentKeys.end(), parentColName) == link->mParentKeys.end())
continue; continue;
auto childCat = cat->db().get(link->mChildCategory);
if (childCat == nullptr or childCat->empty())
continue;
auto childCatValidator = childCat->getCatValidator(); auto childCatValidator = childCat->getCatValidator();
if (childCatValidator == nullptr) if (childCatValidator == nullptr)
continue; continue;
...@@ -3309,7 +3397,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b) ...@@ -3309,7 +3397,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
} }
} }
size_t Row::ColumnForItemTag(const char *itemTag) const size_t Row::ColumnForItemTag(std::string_view itemTag) const
{ {
size_t result = 0; size_t result = 0;
if (mData != nullptr) if (mData != nullptr)
...@@ -3424,7 +3512,6 @@ File::File(File &&rhs) ...@@ -3424,7 +3512,6 @@ File::File(File &&rhs)
File::~File() File::~File()
{ {
delete mHead; delete mHead;
delete mValidator;
} }
void File::append(Datablock *e) void File::append(Datablock *e)
...@@ -3501,7 +3588,7 @@ void File::save(const std::filesystem::path &p) ...@@ -3501,7 +3588,7 @@ void File::save(const std::filesystem::path &p)
void File::load(std::istream &is) void File::load(std::istream &is)
{ {
Validator *saved = mValidator; auto saved = mValidator;
setValidator(nullptr); setValidator(nullptr);
Parser p(is, *this); Parser p(is, *this);
...@@ -3516,7 +3603,7 @@ void File::load(std::istream &is) ...@@ -3516,7 +3603,7 @@ void File::load(std::istream &is)
void File::load(std::istream &is, const std::string &datablock) void File::load(std::istream &is, const std::string &datablock)
{ {
Validator *saved = mValidator; auto saved = mValidator;
setValidator(nullptr); setValidator(nullptr);
Parser p(is, *this); Parser p(is, *this);
...@@ -3549,7 +3636,7 @@ void File::write(std::ostream &os, const std::vector<std::string> &order) ...@@ -3549,7 +3636,7 @@ void File::write(std::ostream &os, const std::vector<std::string> &order)
} }
} }
Datablock *File::get(const std::string &name) const Datablock *File::get(std::string_view name) const
{ {
const Datablock *result = mHead; const Datablock *result = mHead;
while (result != nullptr and not iequals(result->mName, name)) while (result != nullptr and not iequals(result->mName, name))
...@@ -3557,13 +3644,15 @@ Datablock *File::get(const std::string &name) const ...@@ -3557,13 +3644,15 @@ Datablock *File::get(const std::string &name) const
return const_cast<Datablock *>(result); return const_cast<Datablock *>(result);
} }
Datablock &File::operator[](const std::string &name) Datablock &File::operator[](std::string_view name)
{ {
using namespace std::literals;
Datablock *result = mHead; Datablock *result = mHead;
while (result != nullptr and not iequals(result->mName, name)) while (result != nullptr and not iequals(result->mName, name))
result = result->mNext; result = result->mNext;
if (result == nullptr) if (result == nullptr)
throw std::runtime_error("Datablock " + name + " does not exist"); throw std::runtime_error("Datablock " + std::string(name) + " does not exist");
return *result; return *result;
} }
...@@ -3603,67 +3692,10 @@ void File::loadDictionary() ...@@ -3603,67 +3692,10 @@ void File::loadDictionary()
void File::loadDictionary(const char *dict) void File::loadDictionary(const char *dict)
{ {
fs::path dict_name(dict); setValidator(&ValidatorFactory::instance()[dict]);
auto data = loadResource(dict);
if (not data and dict_name.extension().string() != ".dic")
data = loadResource(dict_name.parent_path() / (dict_name.filename().string() + ".dic"));
if (data)
loadDictionary(*data);
else
{
// might be a compressed dictionary on disk
fs::path p = dict;
if (p.extension() == ".dic")
p = p.parent_path() / (p.filename().string() + ".gz");
else
p = p.parent_path() / (p.filename().string() + ".dic.gz");
#if defined(CACHE_DIR) and defined(DATA_DIR)
if (not fs::exists(p))
{
for (const char *dir : {CACHE_DIR, DATA_DIR})
{
auto p2 = fs::path(dir) / p;
if (fs::exists(p2))
{
swap(p, p2);
break;
}
}
}
#endif
if (fs::exists(p))
{
std::ifstream file(p, std::ios::binary);
if (not file.is_open())
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
io::filtering_stream<io::input> in;
in.push(io::gzip_decompressor());
in.push(file);
loadDictionary(in);
}
else
throw std::runtime_error("Dictionary not found or defined (" + dict_name.string() + ")");
}
}
void File::loadDictionary(std::istream &is)
{
std::unique_ptr<Validator> v(new Validator());
DictParser p(*v, is);
p.loadDictionary();
setValidator(v.release());
} }
void File::setValidator(Validator *v) void File::setValidator(const Validator *v)
{ {
mValidator = v; mValidator = v;
......
...@@ -249,7 +249,7 @@ size_t WriteContinuedLine(std::ostream& pdbFile, std::string header, int& count, ...@@ -249,7 +249,7 @@ size_t WriteContinuedLine(std::ostream& pdbFile, std::string header, int& count,
for (auto& line: lines) for (auto& line: lines)
{ {
ba::to_upper(line); // ba::to_upper(line);
pdbFile << header; pdbFile << header;
...@@ -811,7 +811,7 @@ typedef RM<3> RM3; ...@@ -811,7 +811,7 @@ typedef RM<3> RM3;
template<int N> template<int N>
std::ostream& operator<<(std::ostream& os, RM<N>&& rm) std::ostream& operator<<(std::ostream& os, RM<N>&& rm)
{ {
os << "REMARK " << std::setw(3) << std::right << N << " " << rm.mDesc << (rm.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(abs(rm.mWidth)) << std::setprecision(rm.mPrecision); os << "REMARK " << std::setw(3) << std::right << N << " " << rm.mDesc << (rm.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(std::abs(rm.mWidth)) << std::setprecision(rm.mPrecision);
return os; return os;
} }
...@@ -824,7 +824,7 @@ struct SEP ...@@ -824,7 +824,7 @@ struct SEP
std::ostream& operator<<(std::ostream& os, SEP&& sep) std::ostream& operator<<(std::ostream& os, SEP&& sep)
{ {
os << sep.mText << (sep.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(abs(sep.mWidth)) << std::setprecision(sep.mPrecision); os << sep.mText << (sep.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(std::abs(sep.mWidth)) << std::setprecision(sep.mPrecision);
return os; return os;
} }
......
...@@ -42,25 +42,25 @@ namespace cif ...@@ -42,25 +42,25 @@ namespace cif
const uint32_t kMaxLineLength = 132; const uint32_t kMaxLineLength = 132;
const uint8_t kCharTraitsTable[128] = { const uint8_t kCharTraitsTable[128] = {
// 0 1 2 3 4 5 6 7 8 9 a b c d e f // 0 1 2 3 4 5 6 7 8 9 a b c d e f
14, 15, 14, 14, 14, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, // 2 14, 15, 14, 14, 14, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, // 2
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 10, 15, 15, 15, 15, // 3 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 10, 15, 15, 15, 15, // 3
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 4 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 4
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 14, 15, 14, // 5 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 14, 15, 14, // 5
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 6 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // 6
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, // 7 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, // 7
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
CifParserError::CifParserError(uint32_t lineNr, const std::string& message) CifParserError::CifParserError(uint32_t lineNr, const std::string &message)
: std::runtime_error("parse error at line " + std::to_string(lineNr) + ": " + message) : std::runtime_error("parse error at line " + std::to_string(lineNr) + ": " + message)
{ {
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
const char* SacParser::kTokenName[] = { const char *SacParser::kTokenName[] = {
"unknown", "unknown",
"EOF", "EOF",
"DATA", "DATA",
...@@ -69,22 +69,20 @@ const char* SacParser::kTokenName[] = { ...@@ -69,22 +69,20 @@ const char* SacParser::kTokenName[] = {
"SAVE", "SAVE",
"STOP", "STOP",
"Tag", "Tag",
"Value" "Value"};
};
const char* SacParser::kValueName[] = { const char *SacParser::kValueName[] = {
"Int", "Int",
"Float", "Float",
"Numeric", "Numeric",
"String", "String",
"TextField", "TextField",
"Inapplicable", "Inapplicable",
"Unknown" "Unknown"};
};
// -------------------------------------------------------------------- // --------------------------------------------------------------------
SacParser::SacParser(std::istream& is, bool init) SacParser::SacParser(std::istream &is, bool init)
: mData(is) : mData(is)
{ {
mValidate = true; mValidate = true;
...@@ -95,7 +93,7 @@ SacParser::SacParser(std::istream& is, bool init) ...@@ -95,7 +93,7 @@ SacParser::SacParser(std::istream& is, bool init)
mLookahead = getNextToken(); mLookahead = getNextToken();
} }
void SacParser::error(const std::string& msg) void SacParser::error(const std::string &msg)
{ {
throw CifParserError(mLineNr, msg); throw CifParserError(mLineNr, msg);
} }
...@@ -114,7 +112,7 @@ int SacParser::getNextChar() ...@@ -114,7 +112,7 @@ int SacParser::getNextChar()
result = mBuffer.top(); result = mBuffer.top();
mBuffer.pop(); mBuffer.pop();
} }
// very simple CR/LF translation into LF // very simple CR/LF translation into LF
if (result == '\r') if (result == '\r')
{ {
...@@ -123,12 +121,12 @@ int SacParser::getNextChar() ...@@ -123,12 +121,12 @@ int SacParser::getNextChar()
mBuffer.push(lookahead); mBuffer.push(lookahead);
result = '\n'; result = '\n';
} }
mTokenValue += static_cast<char>(result); mTokenValue += static_cast<char>(result);
if (result == '\n') if (result == '\n')
++mLineNr; ++mLineNr;
if (VERBOSE >= 6) if (VERBOSE >= 6)
{ {
std::cerr << "getNextChar => "; std::cerr << "getNextChar => ";
...@@ -137,7 +135,7 @@ int SacParser::getNextChar() ...@@ -137,7 +135,7 @@ int SacParser::getNextChar()
else else
std::cerr << char(result) << std::endl; std::cerr << char(result) << std::endl;
} }
return result; return result;
} }
...@@ -148,7 +146,7 @@ void SacParser::retract() ...@@ -148,7 +146,7 @@ void SacParser::retract()
char ch = mTokenValue.back(); char ch = mTokenValue.back();
if (ch == '\n') if (ch == '\n')
--mLineNr; --mLineNr;
mBuffer.push(ch); mBuffer.push(ch);
mTokenValue.pop_back(); mTokenValue.pop_back();
} }
...@@ -157,25 +155,25 @@ void SacParser::restart() ...@@ -157,25 +155,25 @@ void SacParser::restart()
{ {
while (not mTokenValue.empty()) while (not mTokenValue.empty())
retract(); retract();
switch (mStart) switch (mStart)
{ {
case eStateStart: case eStateStart:
mState = mStart = eStateFloat; mState = mStart = eStateFloat;
break; break;
case eStateFloat: case eStateFloat:
mState = mStart = eStateInt; mState = mStart = eStateInt;
break; break;
case eStateInt: case eStateInt:
mState = mStart = eStateValue; mState = mStart = eStateValue;
break; break;
default: default:
error("Invalid state in SacParser"); error("Invalid state in SacParser");
} }
mBol = false; mBol = false;
} }
...@@ -183,26 +181,26 @@ void SacParser::match(SacParser::CIFToken t) ...@@ -183,26 +181,26 @@ void SacParser::match(SacParser::CIFToken t)
{ {
if (mLookahead != t) if (mLookahead != t)
error(std::string("Unexpected token, expected ") + kTokenName[t] + " but found " + kTokenName[mLookahead]); error(std::string("Unexpected token, expected ") + kTokenName[t] + " but found " + kTokenName[mLookahead]);
mLookahead = getNextToken(); mLookahead = getNextToken();
} }
SacParser::CIFToken SacParser::getNextToken() SacParser::CIFToken SacParser::getNextToken()
{ {
const auto kEOF = std::char_traits<char>::eof(); const auto kEOF = std::char_traits<char>::eof();
CIFToken result = eCIFTokenUnknown; CIFToken result = eCIFTokenUnknown;
int quoteChar = 0; int quoteChar = 0;
mState = mStart = eStateStart; mState = mStart = eStateStart;
mBol = false; mBol = false;
mTokenValue.clear(); mTokenValue.clear();
mTokenType = eCIFValueUnknown; mTokenType = eCIFValueUnknown;
while (result == eCIFTokenUnknown) while (result == eCIFTokenUnknown)
{ {
auto ch = getNextChar(); auto ch = getNextChar();
switch (mState) switch (mState)
{ {
case eStateStart: case eStateStart:
...@@ -233,7 +231,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -233,7 +231,7 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
case eStateWhite: case eStateWhite:
if (ch == kEOF) if (ch == kEOF)
result = eCIFTokenEOF; result = eCIFTokenEOF;
...@@ -246,7 +244,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -246,7 +244,7 @@ SacParser::CIFToken SacParser::getNextToken()
else else
mBol = (ch == '\n'); mBol = (ch == '\n');
break; break;
case eStateComment: case eStateComment:
if (ch == '\n') if (ch == '\n')
{ {
...@@ -259,7 +257,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -259,7 +257,7 @@ SacParser::CIFToken SacParser::getNextToken()
else if (not isAnyPrint(ch)) else if (not isAnyPrint(ch))
error("invalid character in comment"); error("invalid character in comment");
break; break;
case eStateQuestionMark: case eStateQuestionMark:
if (isNonBlank(ch)) if (isNonBlank(ch))
mState = eStateValue; mState = eStateValue;
...@@ -291,10 +289,10 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -291,10 +289,10 @@ SacParser::CIFToken SacParser::getNextToken()
else if (ch == kEOF) else if (ch == kEOF)
error("unterminated textfield"); error("unterminated textfield");
else if (not isAnyPrint(ch)) else if (not isAnyPrint(ch))
// error("invalid character in text field '" + string({ static_cast<char>(ch) }) + "' (" + to_string((int)ch) + ")"); // error("invalid character in text field '" + string({ static_cast<char>(ch) }) + "' (" + to_string((int)ch) + ")");
std::cerr << "invalid character in text field '" << std::string({ static_cast<char>(ch) }) << "' (" << ch << ") line: " << mLineNr << std::endl; std::cerr << "invalid character in text field '" << std::string({static_cast<char>(ch)}) << "' (" << ch << ") line: " << mLineNr << std::endl;
break; break;
case eStateTextField + 1: case eStateTextField + 1:
if (isTextLead(ch) or ch == ' ' or ch == '\t') if (isTextLead(ch) or ch == ' ' or ch == '\t')
mState = eStateTextField; mState = eStateTextField;
...@@ -310,7 +308,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -310,7 +308,7 @@ SacParser::CIFToken SacParser::getNextToken()
else if (ch != '\n') else if (ch != '\n')
error("invalid character in text field"); error("invalid character in text field");
break; break;
case eStateQuotedString: case eStateQuotedString:
if (ch == kEOF) if (ch == kEOF)
error("unterminated quoted string"); error("unterminated quoted string");
...@@ -319,14 +317,14 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -319,14 +317,14 @@ SacParser::CIFToken SacParser::getNextToken()
else if (not isAnyPrint(ch)) else if (not isAnyPrint(ch))
error("invalid character in quoted string"); error("invalid character in quoted string");
break; break;
case eStateQuotedStringQuote: case eStateQuotedStringQuote:
if (isWhite(ch)) if (isWhite(ch))
{ {
retract(); retract();
result = eCIFTokenValue; result = eCIFTokenValue;
mTokenType = eCIFValueString; mTokenType = eCIFValueString;
assert(mTokenValue.length() >= 3); assert(mTokenValue.length() >= 3);
mTokenValue = mTokenValue.substr(1, mTokenValue.length() - 2); mTokenValue = mTokenValue.substr(1, mTokenValue.length() - 2);
} }
...@@ -339,7 +337,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -339,7 +337,7 @@ SacParser::CIFToken SacParser::getNextToken()
else else
error("invalid character in quoted string"); error("invalid character in quoted string");
break; break;
case eStateTag: case eStateTag:
if (not isNonBlank(ch)) if (not isNonBlank(ch))
{ {
...@@ -347,7 +345,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -347,7 +345,7 @@ SacParser::CIFToken SacParser::getNextToken()
result = eCIFTokenTag; result = eCIFTokenTag;
} }
break; break;
case eStateFloat: case eStateFloat:
if (ch == '+' or ch == '-') if (ch == '+' or ch == '-')
{ {
...@@ -358,11 +356,11 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -358,11 +356,11 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
case eStateFloat + 1: case eStateFloat + 1:
// if (ch == '(') // numeric??? // if (ch == '(') // numeric???
// mState = eStateNumericSuffix; // mState = eStateNumericSuffix;
// else // else
if (ch == '.') if (ch == '.')
mState = eStateFloat + 2; mState = eStateFloat + 2;
else if (tolower(ch) == 'e') else if (tolower(ch) == 'e')
...@@ -376,12 +374,12 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -376,12 +374,12 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
// parsed '.' // parsed '.'
case eStateFloat + 2: case eStateFloat + 2:
// if (ch == '(') // numeric??? // if (ch == '(') // numeric???
// mState = eStateNumericSuffix; // mState = eStateNumericSuffix;
// else // else
if (tolower(ch) == 'e') if (tolower(ch) == 'e')
mState = eStateFloat + 3; mState = eStateFloat + 3;
else if (isWhite(ch) or ch == kEOF) else if (isWhite(ch) or ch == kEOF)
...@@ -393,7 +391,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -393,7 +391,7 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
// parsed 'e' // parsed 'e'
case eStateFloat + 3: case eStateFloat + 3:
if (ch == '-' or ch == '+') if (ch == '-' or ch == '+')
...@@ -410,11 +408,11 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -410,11 +408,11 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
case eStateFloat + 5: case eStateFloat + 5:
// if (ch == '(') // if (ch == '(')
// mState = eStateNumericSuffix; // mState = eStateNumericSuffix;
// else // else
if (isWhite(ch) or ch == kEOF) if (isWhite(ch) or ch == kEOF)
{ {
retract(); retract();
...@@ -424,14 +422,14 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -424,14 +422,14 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
case eStateInt: case eStateInt:
if (isdigit(ch) or ch == '+' or ch == '-') if (isdigit(ch) or ch == '+' or ch == '-')
mState = eStateInt + 1; mState = eStateInt + 1;
else else
restart(); restart();
break; break;
case eStateInt + 1: case eStateInt + 1:
if (isWhite(ch) or ch == kEOF) if (isWhite(ch) or ch == kEOF)
{ {
...@@ -442,36 +440,36 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -442,36 +440,36 @@ SacParser::CIFToken SacParser::getNextToken()
else else
restart(); restart();
break; break;
// case eStateNumericSuffix: // case eStateNumericSuffix:
// if (isdigit(ch)) // if (isdigit(ch))
// mState = eStateNumericSuffix + 1; // mState = eStateNumericSuffix + 1;
// else // else
// restart(); // restart();
// break; // break;
// //
// case eStateNumericSuffix + 1: // case eStateNumericSuffix + 1:
// if (ch == ')') // if (ch == ')')
// { // {
// result = eCIFTokenValue; // result = eCIFTokenValue;
// mTokenType = eCIFValueNumeric; // mTokenType = eCIFValueNumeric;
// } // }
// else if (not isdigit(ch)) // else if (not isdigit(ch))
// restart(); // restart();
// break; // break;
case eStateValue: case eStateValue:
if (isNonBlank(ch)) if (isNonBlank(ch))
mState = eStateValue + 1; mState = eStateValue + 1;
else else
error("invalid character at this position"); error("invalid character at this position");
break; break;
case eStateValue + 1: case eStateValue + 1:
if (ch == '_') // first _, check for keywords if (ch == '_') // first _, check for keywords
{ {
std::string s = toLowerCopy(mTokenValue); std::string s = toLowerCopy(mTokenValue);
if (s == "global_") if (s == "global_")
result = eCIFTokenGLOBAL; result = eCIFTokenGLOBAL;
else if (s == "stop_") else if (s == "stop_")
...@@ -493,16 +491,16 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -493,16 +491,16 @@ SacParser::CIFToken SacParser::getNextToken()
if (not isNonBlank(ch)) if (not isNonBlank(ch))
{ {
retract(); retract();
if (tolower(mTokenValue[0]) == 'd') if (tolower(mTokenValue[0]) == 'd')
result = eCIFTokenDATA; result = eCIFTokenDATA;
else else
result = eCIFTokenSAVE; result = eCIFTokenSAVE;
mTokenValue.erase(mTokenValue.begin(), mTokenValue.begin() + 5); mTokenValue.erase(mTokenValue.begin(), mTokenValue.begin() + 5);
} }
break; break;
default: default:
assert(false); assert(false);
error("Invalid state in getNextToken"); error("Invalid state in getNextToken");
...@@ -519,7 +517,7 @@ SacParser::CIFToken SacParser::getNextToken() ...@@ -519,7 +517,7 @@ SacParser::CIFToken SacParser::getNextToken()
std::cerr << " '" << mTokenValue << '\''; std::cerr << " '" << mTokenValue << '\'';
std::cerr << std::endl; std::cerr << std::endl;
} }
return result; return result;
} }
...@@ -530,8 +528,15 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -530,8 +528,15 @@ DatablockIndex SacParser::indexDatablocks()
// first locate the start, as fast as we can // first locate the start, as fast as we can
auto &sb = *mData.rdbuf(); auto &sb = *mData.rdbuf();
enum { enum
start, comment, string, string_quote, qstring, data, data_name {
start,
comment,
string,
string_quote,
qstring,
data,
data_name
} state = start; } state = start;
int quote = 0; int quote = 0;
...@@ -547,7 +552,7 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -547,7 +552,7 @@ DatablockIndex SacParser::indexDatablocks()
case start: case start:
switch (ch) switch (ch)
{ {
case '#': state = comment; break; case '#': state = comment; break;
case 'd': case 'd':
case 'D': case 'D':
state = data; state = data;
...@@ -564,7 +569,7 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -564,7 +569,7 @@ DatablockIndex SacParser::indexDatablocks()
break; break;
} }
break; break;
case comment: case comment:
if (ch == '\n') if (ch == '\n')
state = start; state = start;
...@@ -574,29 +579,29 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -574,29 +579,29 @@ DatablockIndex SacParser::indexDatablocks()
if (ch == quote) if (ch == quote)
state = string_quote; state = string_quote;
break; break;
case string_quote: case string_quote:
if (std::isspace(ch)) if (std::isspace(ch))
state = start; state = start;
else else
state = string; state = string;
break; break;
case qstring: case qstring:
if (ch == ';' and bol) if (ch == ';' and bol)
state = start; state = start;
break; break;
case data: case data:
if (dblk[si] == 0 and isNonBlank(ch)) if (dblk[si] == 0 and isNonBlank(ch))
{ {
datablock = { static_cast<char>(ch) }; datablock = {static_cast<char>(ch)};
state = data_name; state = data_name;
} }
else if (dblk[si++] != ch) else if (dblk[si++] != ch)
state = start; state = start;
break; break;
case data_name: case data_name:
if (isNonBlank(ch)) if (isNonBlank(ch))
datablock.insert(datablock.end(), char(ch)); datablock.insert(datablock.end(), char(ch));
...@@ -604,7 +609,7 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -604,7 +609,7 @@ DatablockIndex SacParser::indexDatablocks()
{ {
if (not datablock.empty()) if (not datablock.empty())
index[datablock] = mData.tellg(); index[datablock] = mData.tellg();
state = start; state = start;
} }
else else
...@@ -618,13 +623,19 @@ DatablockIndex SacParser::indexDatablocks() ...@@ -618,13 +623,19 @@ DatablockIndex SacParser::indexDatablocks()
return index; return index;
} }
bool SacParser::parseSingleDatablock(const std::string& datablock) bool SacParser::parseSingleDatablock(const std::string &datablock)
{ {
// first locate the start, as fast as we can // first locate the start, as fast as we can
auto &sb = *mData.rdbuf(); auto &sb = *mData.rdbuf();
enum { enum
start, comment, string, string_quote, qstring, data {
start,
comment,
string,
string_quote,
qstring,
data
} state = start; } state = start;
int quote = 0; int quote = 0;
...@@ -640,7 +651,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock) ...@@ -640,7 +651,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
case start: case start:
switch (ch) switch (ch)
{ {
case '#': state = comment; break; case '#': state = comment; break;
case 'd': case 'd':
case 'D': case 'D':
state = data; state = data;
...@@ -657,7 +668,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock) ...@@ -657,7 +668,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
break; break;
} }
break; break;
case comment: case comment:
if (ch == '\n') if (ch == '\n')
state = start; state = start;
...@@ -667,19 +678,19 @@ bool SacParser::parseSingleDatablock(const std::string& datablock) ...@@ -667,19 +678,19 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
if (ch == quote) if (ch == quote)
state = string_quote; state = string_quote;
break; break;
case string_quote: case string_quote:
if (std::isspace(ch)) if (std::isspace(ch))
state = start; state = start;
else else
state = string; state = string;
break; break;
case qstring: case qstring:
if (ch == ';' and bol) if (ch == ';' and bol)
state = start; state = start;
break; break;
case data: case data:
if (isspace(ch) and dblk[si] == 0) if (isspace(ch) and dblk[si] == 0)
found = true; found = true;
...@@ -701,7 +712,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock) ...@@ -701,7 +712,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
return found; return found;
} }
bool SacParser::parseSingleDatablock(const std::string& datablock, const DatablockIndex &index) bool SacParser::parseSingleDatablock(const std::string &datablock, const DatablockIndex &index)
{ {
bool result = false; bool result = false;
...@@ -729,14 +740,14 @@ void SacParser::parseFile() ...@@ -729,14 +740,14 @@ void SacParser::parseFile()
case eCIFTokenGLOBAL: case eCIFTokenGLOBAL:
parseGlobal(); parseGlobal();
break; break;
case eCIFTokenDATA: case eCIFTokenDATA:
produceDatablock(mTokenValue); produceDatablock(mTokenValue);
match(eCIFTokenDATA); match(eCIFTokenDATA);
parseDataBlock(); parseDataBlock();
break; break;
default: default:
error("This file does not seem to be an mmCIF file"); error("This file does not seem to be an mmCIF file");
break; break;
...@@ -757,24 +768,24 @@ void SacParser::parseGlobal() ...@@ -757,24 +768,24 @@ void SacParser::parseGlobal()
void SacParser::parseDataBlock() void SacParser::parseDataBlock()
{ {
std::string cat; std::string cat;
while (mLookahead == eCIFTokenLOOP or mLookahead == eCIFTokenTag or mLookahead == eCIFTokenSAVE) while (mLookahead == eCIFTokenLOOP or mLookahead == eCIFTokenTag or mLookahead == eCIFTokenSAVE)
{ {
switch (mLookahead) switch (mLookahead)
{ {
case eCIFTokenLOOP: case eCIFTokenLOOP:
{ {
cat.clear(); // should start a new category cat.clear(); // should start a new category
match(eCIFTokenLOOP); match(eCIFTokenLOOP);
std::vector<std::string> tags; std::vector<std::string> tags;
while (mLookahead == eCIFTokenTag) while (mLookahead == eCIFTokenTag)
{ {
std::string catName, itemName; std::string catName, itemName;
std::tie(catName, itemName) = splitTagName(mTokenValue); std::tie(catName, itemName) = splitTagName(mTokenValue);
if (cat.empty()) if (cat.empty())
{ {
produceCategory(catName); produceCategory(catName);
...@@ -782,27 +793,27 @@ void SacParser::parseDataBlock() ...@@ -782,27 +793,27 @@ void SacParser::parseDataBlock()
} }
else if (not iequals(cat, catName)) else if (not iequals(cat, catName))
error("inconsistent categories in loop_"); error("inconsistent categories in loop_");
tags.push_back(itemName); tags.push_back(itemName);
match(eCIFTokenTag); match(eCIFTokenTag);
} }
while (mLookahead == eCIFTokenValue) while (mLookahead == eCIFTokenValue)
{ {
produceRow(); produceRow();
for (auto tag: tags) for (auto tag : tags)
{ {
produceItem(cat, tag, mTokenValue); produceItem(cat, tag, mTokenValue);
match(eCIFTokenValue); match(eCIFTokenValue);
} }
} }
cat.clear(); cat.clear();
break; break;
} }
case eCIFTokenTag: case eCIFTokenTag:
{ {
std::string catName, itemName; std::string catName, itemName;
...@@ -816,17 +827,17 @@ void SacParser::parseDataBlock() ...@@ -816,17 +827,17 @@ void SacParser::parseDataBlock()
} }
match(eCIFTokenTag); match(eCIFTokenTag);
produceItem(cat, itemName, mTokenValue); produceItem(cat, itemName, mTokenValue);
match(eCIFTokenValue); match(eCIFTokenValue);
break; break;
} }
case eCIFTokenSAVE: case eCIFTokenSAVE:
parseSaveFrame(); parseSaveFrame();
break; break;
default: default:
assert(false); assert(false);
break; break;
...@@ -841,18 +852,20 @@ void SacParser::parseSaveFrame() ...@@ -841,18 +852,20 @@ void SacParser::parseSaveFrame()
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Parser::Parser(std::istream& is, File& f, bool init) Parser::Parser(std::istream &is, File &f, bool init)
: SacParser(is, init), mFile(f), mDataBlock(nullptr) : SacParser(is, init)
, mFile(f)
, mDataBlock(nullptr)
{ {
} }
void Parser::produceDatablock(const std::string& name) void Parser::produceDatablock(const std::string &name)
{ {
mDataBlock = new Datablock(name); mDataBlock = new Datablock(name);
mFile.append(mDataBlock); mFile.append(mDataBlock);
} }
void Parser::produceCategory(const std::string& name) void Parser::produceCategory(const std::string &name)
{ {
if (VERBOSE >= 4) if (VERBOSE >= 4)
std::cerr << "producing category " << name << std::endl; std::cerr << "producing category " << name << std::endl;
...@@ -870,7 +883,7 @@ void Parser::produceRow() ...@@ -870,7 +883,7 @@ void Parser::produceRow()
mRow.lineNr(mLineNr); mRow.lineNr(mLineNr);
} }
void Parser::produceItem(const std::string& category, const std::string& item, const std::string& value) void Parser::produceItem(const std::string &category, const std::string &item, const std::string &value)
{ {
if (VERBOSE >= 4) if (VERBOSE >= 4)
std::cerr << "producing _" << category << '.' << item << " -> " << value << std::endl; std::cerr << "producing _" << category << '.' << item << " -> " << value << std::endl;
...@@ -886,13 +899,15 @@ void Parser::produceItem(const std::string& category, const std::string& item, c ...@@ -886,13 +899,15 @@ void Parser::produceItem(const std::string& category, const std::string& item, c
struct DictParserDataImpl struct DictParserDataImpl
{ {
// temporary values for constructing dictionaries // temporary values for constructing dictionaries
std::vector<ValidateCategory> mCategoryValidators; std::vector<ValidateCategory> mCategoryValidators;
std::map<std::string,std::vector<ValidateItem>> mItemValidators; std::map<std::string, std::vector<ValidateItem>> mItemValidators;
std::set<std::tuple<std::string,std::string>> mLinkedItems; std::set<std::tuple<std::string, std::string>> mLinkedItems;
}; };
DictParser::DictParser(Validator& validator, std::istream& is) DictParser::DictParser(Validator &validator, std::istream &is)
: Parser(is, mFile), mValidator(validator), mImpl(new DictParserDataImpl) : Parser(is, mFile)
, mValidator(validator)
, mImpl(new DictParserDataImpl)
{ {
} }
...@@ -910,9 +925,9 @@ void DictParser::parseSaveFrame() ...@@ -910,9 +925,9 @@ void DictParser::parseSaveFrame()
if (saveFrameName.empty()) if (saveFrameName.empty())
error("Invalid save frame, should contain more than just 'save_' here"); error("Invalid save frame, should contain more than just 'save_' here");
bool isCategorySaveFrame = mTokenValue[0] != '_'; bool isCategorySaveFrame = mTokenValue[0] != '_';
Datablock dict(mTokenValue); Datablock dict(mTokenValue);
Datablock::iterator cat = dict.end(); Datablock::iterator cat = dict.end();
...@@ -921,37 +936,37 @@ void DictParser::parseSaveFrame() ...@@ -921,37 +936,37 @@ void DictParser::parseSaveFrame()
{ {
if (mLookahead == eCIFTokenLOOP) if (mLookahead == eCIFTokenLOOP)
{ {
cat = dict.end(); // should start a new category cat = dict.end(); // should start a new category
match(eCIFTokenLOOP); match(eCIFTokenLOOP);
std::vector<std::string> tags; std::vector<std::string> tags;
while (mLookahead == eCIFTokenTag) while (mLookahead == eCIFTokenTag)
{ {
std::string catName, itemName; std::string catName, itemName;
std::tie(catName, itemName) = splitTagName(mTokenValue); std::tie(catName, itemName) = splitTagName(mTokenValue);
if (cat == dict.end()) if (cat == dict.end())
std::tie(cat, std::ignore) = dict.emplace(catName); std::tie(cat, std::ignore) = dict.emplace(catName);
else if (not iequals(cat->name(), catName)) else if (not iequals(cat->name(), catName))
error("inconsistent categories in loop_"); error("inconsistent categories in loop_");
tags.push_back(itemName); tags.push_back(itemName);
match(eCIFTokenTag); match(eCIFTokenTag);
} }
while (mLookahead == eCIFTokenValue) while (mLookahead == eCIFTokenValue)
{ {
cat->emplace({}); cat->emplace({});
auto row = cat->back(); auto row = cat->back();
for (auto tag: tags) for (auto tag : tags)
{ {
row[tag] = mTokenValue; row[tag] = mTokenValue;
match(eCIFTokenValue); match(eCIFTokenValue);
} }
} }
cat = dict.end(); cat = dict.end();
} }
else else
...@@ -963,75 +978,78 @@ void DictParser::parseSaveFrame() ...@@ -963,75 +978,78 @@ void DictParser::parseSaveFrame()
std::tie(cat, std::ignore) = dict.emplace(catName); std::tie(cat, std::ignore) = dict.emplace(catName);
match(eCIFTokenTag); match(eCIFTokenTag);
if (cat->empty()) if (cat->empty())
cat->emplace({}); cat->emplace({});
cat->back()[itemName] = mTokenValue; cat->back()[itemName] = mTokenValue;
match(eCIFTokenValue); match(eCIFTokenValue);
} }
} }
match(eCIFTokenSAVE); match(eCIFTokenSAVE);
if (isCategorySaveFrame) if (isCategorySaveFrame)
{ {
std::string category = dict.firstItem("_category.id"); std::string category;
cif::tie(category) = dict["category"].front().get("id");
std::vector<std::string> keys; std::vector<std::string> keys;
for (auto k: dict["category_key"]) for (auto k : dict["category_key"])
keys.push_back(std::get<1>(splitTagName(k["name"].as<std::string>()))); keys.push_back(std::get<1>(splitTagName(k["name"].as<std::string>())));
iset groups; iset groups;
for (auto g: dict["category_group"]) for (auto g : dict["category_group"])
groups.insert(g["id"].as<std::string>()); groups.insert(g["id"].as<std::string>());
mImpl->mCategoryValidators.push_back(ValidateCategory{category, keys, groups}); mImpl->mCategoryValidators.push_back(ValidateCategory{category, keys, groups});
} }
else else
{ {
// if the type code is missing, this must be a pointer, just skip it // if the type code is missing, this must be a pointer, just skip it
std::string typeCode = dict.firstItem("_item_type.code"); std::string typeCode;
cif::tie(typeCode) = dict["item_type"].front().get("code");
const ValidateType* tv = nullptr; const ValidateType *tv = nullptr;
if (not (typeCode.empty() or typeCode == "?")) if (not(typeCode.empty() or typeCode == "?"))
tv = mValidator.getValidatorForType(typeCode); tv = mValidator.getValidatorForType(typeCode);
iset ess; iset ess;
for (auto e: dict["item_enumeration"]) for (auto e : dict["item_enumeration"])
ess.insert(e["value"].as<std::string>()); ess.insert(e["value"].as<std::string>());
std::string defaultValue = dict.firstItem("_item_default.value"); std::string defaultValue;
cif::tie(defaultValue) = dict["item_default"].front().get("value");
bool defaultIsNull = false; bool defaultIsNull = false;
if (defaultValue.empty()) if (defaultValue.empty())
{ {
for (auto& r: dict["_item_default"]) for (auto &r : dict["_item_default"])
{ {
defaultIsNull = r["value"].is_null(); defaultIsNull = r["value"].is_null();
break; break;
} }
} }
// collect the dict from our dataBlock and construct validators // collect the dict from our dataBlock and construct validators
for (auto i: dict["item"]) for (auto i : dict["item"])
{ {
std::string tagName, category, mandatory; std::string tagName, category, mandatory;
cif::tie(tagName, category, mandatory) = i.get("name", "category_id", "mandatory_code"); cif::tie(tagName, category, mandatory) = i.get("name", "category_id", "mandatory_code");
std::string catName, itemName; std::string catName, itemName;
std::tie(catName, itemName) = splitTagName(tagName); std::tie(catName, itemName) = splitTagName(tagName);
if (catName.empty() or itemName.empty()) if (catName.empty() or itemName.empty())
error("Invalid tag name in _item.name " + tagName); error("Invalid tag name in _item.name " + tagName);
if (not iequals(category, catName) and not (category.empty() or category == "?")) if (not iequals(category, catName) and not(category.empty() or category == "?"))
error("specified category id does match the implicit category name for tag '" + tagName + '\''); error("specified category id does match the implicit category name for tag '" + tagName + '\'');
else else
category = catName; category = catName;
auto& ivs = mImpl->mItemValidators[category]; auto &ivs = mImpl->mItemValidators[category];
auto vi = find(ivs.begin(), ivs.end(), ValidateItem{itemName}); auto vi = find(ivs.begin(), ivs.end(), ValidateItem{itemName});
if (vi == ivs.end()) if (vi == ivs.end())
ivs.push_back(ValidateItem{itemName, iequals(mandatory, "yes"), tv, ess, defaultValue, defaultIsNull}); ivs.push_back(ValidateItem{itemName, iequals(mandatory, "yes"), tv, ess, defaultValue, defaultIsNull});
...@@ -1043,7 +1061,7 @@ void DictParser::parseSaveFrame() ...@@ -1043,7 +1061,7 @@ void DictParser::parseSaveFrame()
if (VERBOSE > 2) if (VERBOSE > 2)
{ {
std::cerr << "inconsistent mandatory value for " << tagName << " in dictionary" << std::endl; std::cerr << "inconsistent mandatory value for " << tagName << " in dictionary" << std::endl;
if (iequals(tagName, saveFrameName)) if (iequals(tagName, saveFrameName))
std::cerr << "choosing " << mandatory << std::endl; std::cerr << "choosing " << mandatory << std::endl;
else else
...@@ -1060,7 +1078,7 @@ void DictParser::parseSaveFrame() ...@@ -1060,7 +1078,7 @@ void DictParser::parseSaveFrame()
std::cerr << "inconsistent type for " << tagName << " in dictionary" << std::endl; std::cerr << "inconsistent type for " << tagName << " in dictionary" << std::endl;
} }
// vi->mMandatory = (iequals(mandatory, "yes")); // vi->mMandatory = (iequals(mandatory, "yes"));
if (vi->mType == nullptr) if (vi->mType == nullptr)
vi->mType = tv; vi->mType = tv;
...@@ -1070,14 +1088,14 @@ void DictParser::parseSaveFrame() ...@@ -1070,14 +1088,14 @@ void DictParser::parseSaveFrame()
// ... // ...
} }
} }
// collect the dict from our dataBlock and construct validators // collect the dict from our dataBlock and construct validators
for (auto i: dict["item_linked"]) for (auto i : dict["item_linked"])
{ {
std::string childTagName, parentTagName; std::string childTagName, parentTagName;
cif::tie(childTagName, parentTagName) = i.get("child_name", "parent_name"); cif::tie(childTagName, parentTagName) = i.get("child_name", "parent_name");
mImpl->mLinkedItems.emplace(childTagName, parentTagName); mImpl->mLinkedItems.emplace(childTagName, parentTagName);
} }
} }
...@@ -1088,20 +1106,20 @@ void DictParser::linkItems() ...@@ -1088,20 +1106,20 @@ void DictParser::linkItems()
if (not mDataBlock) if (not mDataBlock)
error("no datablock"); error("no datablock");
auto& dict = *mDataBlock; auto &dict = *mDataBlock;
// links are identified by a parent category, a child category and a group ID // links are identified by a parent category, a child category and a group ID
using key_type = std::tuple<std::string,std::string,int>; using key_type = std::tuple<std::string, std::string, int>;
std::map<key_type,size_t> linkIndex; std::map<key_type, size_t> linkIndex;
// Each link group consists of a set of keys // Each link group consists of a set of keys
std::vector<std::tuple<std::vector<std::string>,std::vector<std::string>>> linkKeys; std::vector<std::tuple<std::vector<std::string>, std::vector<std::string>>> linkKeys;
auto addLink = [&](size_t ix, const std::string& pk, const std::string& ck) auto addLink = [&](size_t ix, const std::string &pk, const std::string &ck)
{ {
auto&& [pkeys, ckeys] = linkKeys.at(ix); auto &&[pkeys, ckeys] = linkKeys.at(ix);
bool found = false; bool found = false;
for (size_t i = 0; i < pkeys.size(); ++i) for (size_t i = 0; i < pkeys.size(); ++i)
...@@ -1120,29 +1138,29 @@ void DictParser::linkItems() ...@@ -1120,29 +1138,29 @@ void DictParser::linkItems()
} }
}; };
auto& linkedGroupList = dict["pdbx_item_linked_group_list"]; auto &linkedGroupList = dict["pdbx_item_linked_group_list"];
for (auto gl: linkedGroupList) for (auto gl : linkedGroupList)
{ {
std::string child, parent; std::string child, parent;
int link_group_id; int link_group_id;
cif::tie(child, parent, link_group_id) = gl.get("child_name", "parent_name", "link_group_id"); cif::tie(child, parent, link_group_id) = gl.get("child_name", "parent_name", "link_group_id");
auto civ = mValidator.getValidatorForItem(child); auto civ = mValidator.getValidatorForItem(child);
if (civ == nullptr) if (civ == nullptr)
error("in pdbx_item_linked_group_list, item '" + child + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + child + "' is not specified");
auto piv = mValidator.getValidatorForItem(parent); auto piv = mValidator.getValidatorForItem(parent);
if (piv == nullptr) if (piv == nullptr)
error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified");
key_type key{ piv->mCategory->mName, civ->mCategory->mName, link_group_id }; key_type key{piv->mCategory->mName, civ->mCategory->mName, link_group_id};
if (not linkIndex.count(key)) if (not linkIndex.count(key))
{ {
linkIndex[key] = linkKeys.size(); linkIndex[key] = linkKeys.size();
linkKeys.push_back({}); linkKeys.push_back({});
} }
size_t ix = linkIndex.at(key); size_t ix = linkIndex.at(key);
addLink(ix, piv->mTag, civ->mTag); addLink(ix, piv->mTag, civ->mTag);
} }
...@@ -1151,35 +1169,35 @@ void DictParser::linkItems() ...@@ -1151,35 +1169,35 @@ void DictParser::linkItems()
if (linkedGroupList.empty()) if (linkedGroupList.empty())
{ {
// for links recorded in categories but not in pdbx_item_linked_group_list // for links recorded in categories but not in pdbx_item_linked_group_list
for (auto li: mImpl->mLinkedItems) for (auto li : mImpl->mLinkedItems)
{ {
std::string child, parent; std::string child, parent;
std::tie(child, parent) = li; std::tie(child, parent) = li;
auto civ = mValidator.getValidatorForItem(child); auto civ = mValidator.getValidatorForItem(child);
if (civ == nullptr) if (civ == nullptr)
error("in pdbx_item_linked_group_list, item '" + child + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + child + "' is not specified");
auto piv = mValidator.getValidatorForItem(parent); auto piv = mValidator.getValidatorForItem(parent);
if (piv == nullptr) if (piv == nullptr)
error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified");
key_type key{ piv->mCategory->mName, civ->mCategory->mName, 0 }; key_type key{piv->mCategory->mName, civ->mCategory->mName, 0};
if (not linkIndex.count(key)) if (not linkIndex.count(key))
{ {
linkIndex[key] = linkKeys.size(); linkIndex[key] = linkKeys.size();
linkKeys.push_back({}); linkKeys.push_back({});
} }
size_t ix = linkIndex.at(key); size_t ix = linkIndex.at(key);
addLink(ix, piv->mTag, civ->mTag); addLink(ix, piv->mTag, civ->mTag);
} }
} }
auto& linkedGroup = dict["pdbx_item_linked_group"]; auto &linkedGroup = dict["pdbx_item_linked_group"];
// now store the links in the validator // now store the links in the validator
for (auto& kv: linkIndex) for (auto &kv : linkIndex)
{ {
ValidateLink link = {}; ValidateLink link = {};
std::tie(link.mParentCategory, link.mChildCategory, link.mLinkGroupID) = kv.first; std::tie(link.mParentCategory, link.mChildCategory, link.mLinkGroupID) = kv.first;
...@@ -1187,7 +1205,7 @@ void DictParser::linkItems() ...@@ -1187,7 +1205,7 @@ void DictParser::linkItems()
std::tie(link.mParentKeys, link.mChildKeys) = linkKeys[kv.second]; std::tie(link.mParentKeys, link.mChildKeys) = linkKeys[kv.second];
// look up the label // look up the label
for (auto r: linkedGroup.find(cif::Key("category_id") == link.mChildCategory and cif::Key("link_group_id") == link.mLinkGroupID)) for (auto r : linkedGroup.find(cif::Key("category_id") == link.mChildCategory and cif::Key("link_group_id") == link.mLinkGroupID))
{ {
link.mLinkGroupLabel = r["label"].as<std::string>(); link.mLinkGroupLabel = r["label"].as<std::string>();
break; break;
...@@ -1197,22 +1215,22 @@ void DictParser::linkItems() ...@@ -1197,22 +1215,22 @@ void DictParser::linkItems()
} }
// now make sure the itemType is specified for all itemValidators // now make sure the itemType is specified for all itemValidators
for (auto& cv: mValidator.mCategoryValidators) for (auto &cv : mValidator.mCategoryValidators)
{ {
for (auto& iv: cv.mItemValidators) for (auto &iv : cv.mItemValidators)
{ {
if (iv.mType == nullptr) if (iv.mType == nullptr)
std::cerr << "Missing item_type for " << iv.mTag << std::endl; std::cerr << "Missing item_type for " << iv.mTag << std::endl;
} }
} }
} }
void DictParser::loadDictionary() void DictParser::loadDictionary()
{ {
std::unique_ptr<Datablock> dict; std::unique_ptr<Datablock> dict;
Datablock* savedDatablock = mDataBlock; Datablock *savedDatablock = mDataBlock;
try try
{ {
while (mLookahead != eCIFTokenEOF) while (mLookahead != eCIFTokenEOF)
...@@ -1222,12 +1240,12 @@ void DictParser::loadDictionary() ...@@ -1222,12 +1240,12 @@ void DictParser::loadDictionary()
case eCIFTokenGLOBAL: case eCIFTokenGLOBAL:
parseGlobal(); parseGlobal();
break; break;
default: default:
{ {
dict.reset(new Datablock(mTokenValue)); // dummy datablock, for constructing the validator only dict.reset(new Datablock(mTokenValue)); // dummy datablock, for constructing the validator only
mDataBlock = dict.get(); mDataBlock = dict.get();
match(eCIFTokenDATA); match(eCIFTokenDATA);
parseDataBlock(); parseDataBlock();
break; break;
...@@ -1235,29 +1253,29 @@ void DictParser::loadDictionary() ...@@ -1235,29 +1253,29 @@ void DictParser::loadDictionary()
} }
} }
} }
catch (const std::exception&) catch (const std::exception &)
{ {
std::cerr << "Error parsing dictionary" << std::endl; std::cerr << "Error parsing dictionary" << std::endl;
throw; throw;
} }
// store all validators // store all validators
for (auto& ic: mImpl->mCategoryValidators) for (auto &ic : mImpl->mCategoryValidators)
mValidator.addCategoryValidator(std::move(ic)); mValidator.addCategoryValidator(std::move(ic));
mImpl->mCategoryValidators.clear(); mImpl->mCategoryValidators.clear();
for (auto& iv: mImpl->mItemValidators) for (auto &iv : mImpl->mItemValidators)
{ {
auto cv = mValidator.getValidatorForCategory(iv.first); auto cv = mValidator.getValidatorForCategory(iv.first);
if (cv == nullptr) if (cv == nullptr)
error("Undefined category '" + iv.first); error("Undefined category '" + iv.first);
for (auto& v: iv.second) for (auto &v : iv.second)
const_cast<ValidateCategory*>(cv)->addItemValidator(std::move(v)); const_cast<ValidateCategory *>(cv)->addItemValidator(std::move(v));
} }
// check all item validators for having a typeValidator // check all item validators for having a typeValidator
if (dict) if (dict)
linkItems(); linkItems();
...@@ -1280,47 +1298,45 @@ void DictParser::loadDictionary() ...@@ -1280,47 +1298,45 @@ void DictParser::loadDictionary()
bool DictParser::collectItemTypes() bool DictParser::collectItemTypes()
{ {
bool result = false; bool result = false;
if (not mDataBlock) if (not mDataBlock)
error("no datablock"); error("no datablock");
auto& dict = *mDataBlock; auto &dict = *mDataBlock;
for (auto& t: dict["item_type_list"]) for (auto &t : dict["item_type_list"])
{ {
std::string code, primitiveCode, construct; std::string code, primitiveCode, construct;
cif::tie(code, primitiveCode, construct) = t.get("code", "primitive_code", "construct"); cif::tie(code, primitiveCode, construct) = t.get("code", "primitive_code", "construct");
ba::replace_all(construct, "\\n", "\n"); ba::replace_all(construct, "\\n", "\n");
ba::replace_all(construct, "\\t", "\t"); ba::replace_all(construct, "\\t", "\t");
ba::replace_all(construct, "\\\n", ""); ba::replace_all(construct, "\\\n", "");
try try
{ {
ValidateType v = { ValidateType v = {
code, mapToPrimitiveType(primitiveCode), boost::regex(construct, boost::regex::extended | boost::regex::optimize) code, mapToPrimitiveType(primitiveCode), boost::regex(construct, boost::regex::extended | boost::regex::optimize)};
};
mValidator.addTypeValidator(std::move(v)); mValidator.addTypeValidator(std::move(v));
} }
catch (const std::exception&) catch (const std::exception &)
{ {
throw_with_nested(CifParserError(t.lineNr(), "error in regular expression")); throw_with_nested(CifParserError(t.lineNr(), "error in regular expression"));
} }
// Do not replace an already defined type validator, this won't work with pdbx_v40 // Do not replace an already defined type validator, this won't work with pdbx_v40
// as it has a name that is too strict for its own names :-) // as it has a name that is too strict for its own names :-)
// if (mFileImpl.mTypeValidators.count(v)) // if (mFileImpl.mTypeValidators.count(v))
// mFileImpl.mTypeValidators.erase(v); // mFileImpl.mTypeValidators.erase(v);
if (VERBOSE >= 5) if (VERBOSE >= 5)
std::cerr << "Added type " << code << " (" << primitiveCode << ") => " << construct << std::endl; std::cerr << "Added type " << code << " (" << primitiveCode << ") => " << construct << std::endl;
result = true; result = true;
} }
return result; return result;
} }
} // namespace cif
}
...@@ -123,11 +123,12 @@ const uint8_t kCharToLowerMap[256] = ...@@ -123,11 +123,12 @@ const uint8_t kCharToLowerMap[256] =
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool iequals(const std::string &a, const std::string &b) bool iequals(std::string_view a, std::string_view b)
{ {
bool result = a.length() == b.length(); bool result = a.length() == b.length();
for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end() and bi != b.end(); ++ai, ++bi) for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end(); ++ai, ++bi)
result = tolower(*ai) == tolower(*bi); result = kCharToLowerMap[uint8_t(*ai)] == kCharToLowerMap[uint8_t(*bi)];
// result = tolower(*ai) == tolower(*bi);
return result; return result;
} }
...@@ -140,7 +141,7 @@ bool iequals(const char *a, const char *b) ...@@ -140,7 +141,7 @@ bool iequals(const char *a, const char *b)
return result and *a == *b; return result and *a == *b;
} }
int icompare(const std::string &a, const std::string &b) int icompare(std::string_view a, std::string_view b)
{ {
int d = 0; int d = 0;
auto ai = a.begin(), bi = b.begin(); auto ai = a.begin(), bi = b.begin();
...@@ -193,7 +194,7 @@ std::string toLowerCopy(const std::string &s) ...@@ -193,7 +194,7 @@ std::string toLowerCopy(const std::string &s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string, std::string> splitTagName(const std::string &tag) std::tuple<std::string, std::string> splitTagName(std::string_view tag)
{ {
if (tag.empty()) if (tag.empty())
throw std::runtime_error("empty tag"); throw std::runtime_error("empty tag");
......
...@@ -24,32 +24,39 @@ ...@@ -24,32 +24,39 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <fstream>
#include <filesystem>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp" #include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp" #include "cif++/CifValidator.hpp"
namespace ba = boost::algorithm; namespace ba = boost::algorithm;
namespace fs = std::filesystem;
namespace io = boost::iostreams;
extern int VERBOSE; extern int VERBOSE;
namespace cif namespace cif
{ {
ValidationError::ValidationError(const std::string& msg) ValidationError::ValidationError(const std::string &msg)
: mMsg(msg) : mMsg(msg)
{ {
} }
ValidationError::ValidationError(const std::string& cat, const std::string& item, const std::string& msg) ValidationError::ValidationError(const std::string &cat, const std::string &item, const std::string &msg)
: mMsg("When validating _" + cat + '.' + item + ": " + msg) : mMsg("When validating _" + cat + '.' + item + ": " + msg)
{ {
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
DDL_PrimitiveType mapToPrimitiveType(const std::string& s) DDL_PrimitiveType mapToPrimitiveType(std::string_view s)
{ {
DDL_PrimitiveType result; DDL_PrimitiveType result;
if (iequals(s, "char")) if (iequals(s, "char"))
...@@ -65,10 +72,10 @@ DDL_PrimitiveType mapToPrimitiveType(const std::string& s) ...@@ -65,10 +72,10 @@ DDL_PrimitiveType mapToPrimitiveType(const std::string& s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
int ValidateType::compare(const char* a, const char* b) const int ValidateType::compare(const char *a, const char *b) const
{ {
int result = 0; int result = 0;
if (*a == 0) if (*a == 0)
result = *b == 0 ? 0 : -1; result = *b == 0 ? 0 : -1;
else if (*b == 0) else if (*b == 0)
...@@ -83,7 +90,7 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -83,7 +90,7 @@ int ValidateType::compare(const char* a, const char* b) const
{ {
double da = strtod(a, nullptr); double da = strtod(a, nullptr);
double db = strtod(b, nullptr); double db = strtod(b, nullptr);
auto d = da - db; auto d = da - db;
if (std::abs(d) > std::numeric_limits<double>::epsilon()) if (std::abs(d) > std::numeric_limits<double>::epsilon())
{ {
...@@ -94,13 +101,13 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -94,13 +101,13 @@ int ValidateType::compare(const char* a, const char* b) const
} }
break; break;
} }
case DDL_PrimitiveType::UChar: case DDL_PrimitiveType::UChar:
case DDL_PrimitiveType::Char: case DDL_PrimitiveType::Char:
{ {
// CIF is guaranteed to have ascii only, therefore this primitive code will do // CIF is guaranteed to have ascii only, therefore this primitive code will do
// also, we're collapsing spaces // also, we're collapsing spaces
auto ai = a, bi = b; auto ai = a, bi = b;
for (;;) for (;;)
{ {
...@@ -115,7 +122,7 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -115,7 +122,7 @@ int ValidateType::compare(const char* a, const char* b) const
result = 1; result = 1;
break; break;
} }
char ca = *ai; char ca = *ai;
char cb = *bi; char cb = *bi;
...@@ -124,12 +131,12 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -124,12 +131,12 @@ int ValidateType::compare(const char* a, const char* b) const
ca = tolower(ca); ca = tolower(ca);
cb = tolower(cb); cb = tolower(cb);
} }
result = ca - cb; result = ca - cb;
if (result != 0) if (result != 0)
break; break;
if (ca == ' ') if (ca == ' ')
{ {
while (ai[1] == ' ') while (ai[1] == ' ')
...@@ -137,21 +144,21 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -137,21 +144,21 @@ int ValidateType::compare(const char* a, const char* b) const
while (bi[1] == ' ') while (bi[1] == ' ')
++bi; ++bi;
} }
++ai; ++ai;
++bi; ++bi;
} }
break; break;
} }
} }
} }
catch (const std::invalid_argument& ex) catch (const std::invalid_argument &ex)
{ {
result = 1; result = 1;
} }
} }
return result; return result;
} }
...@@ -165,13 +172,13 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -165,13 +172,13 @@ int ValidateType::compare(const char* a, const char* b) const
// //
// if (mType == nullptr and parent != nullptr) // if (mType == nullptr and parent != nullptr)
// mType = parent->mType; // mType = parent->mType;
// //
// if (parent != nullptr) // if (parent != nullptr)
// { // {
// mLinked.push_back({parent, parentItem, childItem}); // mLinked.push_back({parent, parentItem, childItem});
// //
// parent->mChildren.insert(this); // parent->mChildren.insert(this);
//// ////
//// if (mCategory->mKeys == std::vector<std::string>{mTag}) //// if (mCategory->mKeys == std::vector<std::string>{mTag})
//// parent->mForeignKeys.insert(this); //// parent->mForeignKeys.insert(this);
// } // }
...@@ -194,7 +201,7 @@ void ValidateItem::operator()(std::string value) const ...@@ -194,7 +201,7 @@ void ValidateItem::operator()(std::string value) const
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void ValidateCategory::addItemValidator(ValidateItem&& v) void ValidateCategory::addItemValidator(ValidateItem &&v)
{ {
if (v.mMandatory) if (v.mMandatory)
mMandatoryFields.insert(v.mTag); mMandatoryFields.insert(v.mTag);
...@@ -206,10 +213,10 @@ void ValidateCategory::addItemValidator(ValidateItem&& v) ...@@ -206,10 +213,10 @@ void ValidateCategory::addItemValidator(ValidateItem&& v)
std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl; std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl;
} }
const ValidateItem* ValidateCategory::getValidatorForItem(std::string tag) const const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) const
{ {
const ValidateItem* result = nullptr; const ValidateItem *result = nullptr;
auto i = mItemValidators.find(ValidateItem{tag}); auto i = mItemValidators.find(ValidateItem{std::string(tag)});
if (i != mItemValidators.end()) if (i != mItemValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -219,26 +226,29 @@ const ValidateItem* ValidateCategory::getValidatorForItem(std::string tag) const ...@@ -219,26 +226,29 @@ const ValidateItem* ValidateCategory::getValidatorForItem(std::string tag) const
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Validator::Validator() Validator::Validator(std::string_view name, std::istream &is)
: mName(name)
{ {
DictParser p(*this, is);
p.loadDictionary();
} }
Validator::~Validator() Validator::~Validator()
{ {
} }
void Validator::addTypeValidator(ValidateType&& v) void Validator::addTypeValidator(ValidateType &&v)
{ {
auto r = mTypeValidators.insert(std::move(v)); auto r = mTypeValidators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for type " << v.mName << std::endl; std::cout << "Could not add validator for type " << v.mName << std::endl;
} }
const ValidateType* Validator::getValidatorForType(std::string typeCode) const const ValidateType *Validator::getValidatorForType(std::string_view typeCode) const
{ {
const ValidateType* result = nullptr; const ValidateType *result = nullptr;
auto i = mTypeValidators.find(ValidateType{ typeCode, DDL_PrimitiveType::Char, boost::regex() }); auto i = mTypeValidators.find(ValidateType{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()});
if (i != mTypeValidators.end()) if (i != mTypeValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -246,17 +256,17 @@ const ValidateType* Validator::getValidatorForType(std::string typeCode) const ...@@ -246,17 +256,17 @@ const ValidateType* Validator::getValidatorForType(std::string typeCode) const
return result; return result;
} }
void Validator::addCategoryValidator(ValidateCategory&& v) void Validator::addCategoryValidator(ValidateCategory &&v)
{ {
auto r = mCategoryValidators.insert(std::move(v)); auto r = mCategoryValidators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for category " << v.mName << std::endl; std::cout << "Could not add validator for category " << v.mName << std::endl;
} }
const ValidateCategory* Validator::getValidatorForCategory(std::string category) const const ValidateCategory *Validator::getValidatorForCategory(std::string_view category) const
{ {
const ValidateCategory* result = nullptr; const ValidateCategory *result = nullptr;
auto i = mCategoryValidators.find(ValidateCategory{category}); auto i = mCategoryValidators.find(ValidateCategory{std::string(category)});
if (i != mCategoryValidators.end()) if (i != mCategoryValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -264,16 +274,16 @@ const ValidateCategory* Validator::getValidatorForCategory(std::string category) ...@@ -264,16 +274,16 @@ const ValidateCategory* Validator::getValidatorForCategory(std::string category)
return result; return result;
} }
ValidateItem* Validator::getValidatorForItem(std::string tag) const ValidateItem *Validator::getValidatorForItem(std::string_view tag) const
{ {
ValidateItem* result = nullptr; ValidateItem *result = nullptr;
std::string cat, item; std::string cat, item;
std::tie(cat, item) = splitTagName(tag); std::tie(cat, item) = splitTagName(tag);
auto* cv = getValidatorForCategory(cat); auto *cv = getValidatorForCategory(cat);
if (cv != nullptr) if (cv != nullptr)
result = const_cast<ValidateItem*>(cv->getValidatorForItem(item)); result = const_cast<ValidateItem *>(cv->getValidatorForItem(item));
if (result == nullptr and VERBOSE > 4) if (result == nullptr and VERBOSE > 4)
std::cout << "No validator for item " << tag << std::endl; std::cout << "No validator for item " << tag << std::endl;
...@@ -281,15 +291,15 @@ ValidateItem* Validator::getValidatorForItem(std::string tag) const ...@@ -281,15 +291,15 @@ ValidateItem* Validator::getValidatorForItem(std::string tag) const
return result; return result;
} }
void Validator::addLinkValidator(ValidateLink&& v) void Validator::addLinkValidator(ValidateLink &&v)
{ {
assert(v.mParentKeys.size() == v.mChildKeys.size()); assert(v.mParentKeys.size() == v.mChildKeys.size());
if (v.mParentKeys.size() != v.mChildKeys.size()) if (v.mParentKeys.size() != v.mChildKeys.size())
throw std::runtime_error("unequal number of keys for parent and child in link"); throw std::runtime_error("unequal number of keys for parent and child in link");
auto pcv = getValidatorForCategory(v.mParentCategory); auto pcv = getValidatorForCategory(v.mParentCategory);
auto ccv = getValidatorForCategory(v.mChildCategory); auto ccv = getValidatorForCategory(v.mChildCategory);
if (pcv == nullptr) if (pcv == nullptr)
throw std::runtime_error("unknown parent category " + v.mParentCategory); throw std::runtime_error("unknown parent category " + v.mParentCategory);
...@@ -299,48 +309,48 @@ void Validator::addLinkValidator(ValidateLink&& v) ...@@ -299,48 +309,48 @@ void Validator::addLinkValidator(ValidateLink&& v)
for (size_t i = 0; i < v.mParentKeys.size(); ++i) for (size_t i = 0; i < v.mParentKeys.size(); ++i)
{ {
auto piv = pcv->getValidatorForItem(v.mParentKeys[i]); auto piv = pcv->getValidatorForItem(v.mParentKeys[i]);
if (piv == nullptr) if (piv == nullptr)
throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]); throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]);
auto civ = ccv->getValidatorForItem(v.mChildKeys[i]); auto civ = ccv->getValidatorForItem(v.mChildKeys[i]);
if (civ == nullptr) if (civ == nullptr)
throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]); throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]);
if (civ->mType == nullptr and piv->mType != nullptr) if (civ->mType == nullptr and piv->mType != nullptr)
const_cast<ValidateItem*>(civ)->mType = piv->mType; const_cast<ValidateItem *>(civ)->mType = piv->mType;
} }
mLinkValidators.emplace_back(std::move(v)); mLinkValidators.emplace_back(std::move(v));
} }
std::vector<const ValidateLink*> Validator::getLinksForParent(const std::string& category) const std::vector<const ValidateLink *> Validator::getLinksForParent(std::string_view category) const
{ {
std::vector<const ValidateLink*> result; std::vector<const ValidateLink *> result;
for (auto& l: mLinkValidators) for (auto &l : mLinkValidators)
{ {
if (l.mParentCategory == category) if (l.mParentCategory == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
std::vector<const ValidateLink*> Validator::getLinksForChild(const std::string& category) const std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view category) const
{ {
std::vector<const ValidateLink*> result; std::vector<const ValidateLink *> result;
for (auto& l: mLinkValidators) for (auto &l : mLinkValidators)
{ {
if (l.mChildCategory == category) if (l.mChildCategory == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
void Validator::reportError(const std::string& msg, bool fatal) void Validator::reportError(const std::string &msg, bool fatal) const
{ {
if (mStrict or fatal) if (mStrict or fatal)
throw ValidationError(msg); throw ValidationError(msg);
...@@ -348,4 +358,78 @@ void Validator::reportError(const std::string& msg, bool fatal) ...@@ -348,4 +358,78 @@ void Validator::reportError(const std::string& msg, bool fatal)
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
// --------------------------------------------------------------------
ValidatorFactory ValidatorFactory::sInstance;
ValidatorFactory::ValidatorFactory()
{
}
const Validator &ValidatorFactory::operator[](std::string_view dictionary)
{
std::lock_guard lock(mMutex);
for (auto &validator : mValidators)
{
if (iequals(validator.mName, dictionary))
return validator;
}
// not found, add it
fs::path dict_name(dictionary);
auto data = loadResource(dictionary);
if (not data and dict_name.extension().string() != ".dic")
data = loadResource(dict_name.parent_path() / (dict_name.filename().string() + ".dic"));
if (data)
mValidators.emplace_back(dictionary, *data);
else
{
// might be a compressed dictionary on disk
fs::path p = dictionary;
if (p.extension() == ".dic")
p = p.parent_path() / (p.filename().string() + ".gz");
else
p = p.parent_path() / (p.filename().string() + ".dic.gz");
#if defined(CACHE_DIR) and defined(DATA_DIR)
if (not fs::exists(p))
{
for (const char *dir : {CACHE_DIR, DATA_DIR})
{
auto p2 = fs::path(dir) / p;
if (fs::exists(p2))
{
swap(p, p2);
break;
}
}
}
#endif
if (fs::exists(p))
{
std::ifstream file(p, std::ios::binary);
if (not file.is_open())
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
io::filtering_stream<io::input> in;
in.push(io::gzip_decompressor());
in.push(file);
mValidators.emplace_back(dictionary, in);
}
else
throw std::runtime_error("Dictionary not found or defined (" + dict_name.string() + ")");
}
assert(iequals(mValidators.back().mName, dictionary));
return mValidators.back();
} }
} // namespace cif
...@@ -128,6 +128,8 @@ Compound::Compound(cif::Datablock &db) ...@@ -128,6 +128,8 @@ Compound::Compound(cif::Datablock &db)
// The name should not contain newline characters since that triggers validation errors later on // The name should not contain newline characters since that triggers validation errors later on
ba::replace_all(mName, "\n", ""); ba::replace_all(mName, "\n", "");
mGroup = "non-polymer";
auto &chemCompAtom = db["chem_comp_atom"]; auto &chemCompAtom = db["chem_comp_atom"];
for (auto row : chemCompAtom) for (auto row : chemCompAtom)
{ {
...@@ -151,10 +153,11 @@ Compound::Compound(cif::Datablock &db) ...@@ -151,10 +153,11 @@ Compound::Compound(cif::Datablock &db)
} }
} }
Compound::Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type) Compound::Compound(cif::Datablock &db, const std::string &id, const std::string &name, const std::string &type, const std::string &group)
: mID(id) : mID(id)
, mName(name) , mName(name)
, mType(type) , mType(type)
, mGroup(group)
{ {
auto &chemCompAtom = db["chem_comp_atom"]; auto &chemCompAtom = db["chem_comp_atom"];
for (auto row : chemCompAtom) for (auto row : chemCompAtom)
...@@ -411,7 +414,7 @@ CompoundFactoryImpl::CompoundFactoryImpl(const std::filesystem::path &file, std: ...@@ -411,7 +414,7 @@ CompoundFactoryImpl::CompoundFactoryImpl(const std::filesystem::path &file, std:
auto &db = cifFile["comp_" + id]; auto &db = cifFile["comp_" + id];
mCompounds.push_back(new Compound(db, id, name, type)); mCompounds.push_back(new Compound(db, id, name, type, group));
} }
} }
else else
...@@ -617,7 +620,7 @@ Compound *CCP4CompoundFactoryImpl::create(const std::string &id) ...@@ -617,7 +620,7 @@ Compound *CCP4CompoundFactoryImpl::create(const std::string &id)
else else
type = "non-polymer"; type = "non-polymer";
mCompounds.push_back(new Compound(db, id, name, type)); mCompounds.push_back(new Compound(db, id, name, type, group));
result = mCompounds.back(); result = mCompounds.back();
} }
} }
......
...@@ -1540,7 +1540,8 @@ void PDBFileParser::ParseTitle() ...@@ -1540,7 +1540,8 @@ void PDBFileParser::ParseTitle()
while (mRec->is("CAVEAT")) // 1 - 6 Record name "CAVEAT" while (mRec->is("CAVEAT")) // 1 - 6 Record name "CAVEAT"
{ {
getCategory("database_PDB_caveat")->emplace({ getCategory("database_PDB_caveat")->emplace({
{"id", caveatID++}, {"text", std::string{mRec->vS(20)}} // 20 - 79 String comment Free text giving the reason for the CAVEAT. {"id", caveatID++},
{"text", std::string{mRec->vS(20)}} // 20 - 79 String comment Free text giving the reason for the CAVEAT.
}); });
GetNextRecord(); GetNextRecord();
...@@ -1674,7 +1675,9 @@ void PDBFileParser::ParseTitle() ...@@ -1674,7 +1675,9 @@ void PDBFileParser::ParseTitle()
if (not(keywords.empty() and pdbxKeywords.empty())) if (not(keywords.empty() and pdbxKeywords.empty()))
{ {
getCategory("struct_keywords")->emplace({{"entry_id", mStructureID}, {"pdbx_keywords", keywords}, {"text", pdbxKeywords}}); getCategory("struct_keywords")->emplace({{"entry_id", mStructureID},
{"pdbx_keywords", keywords},
{"text", pdbxKeywords}});
} }
// EXPDTA // EXPDTA
...@@ -1794,13 +1797,18 @@ void PDBFileParser::ParseTitle() ...@@ -1794,13 +1797,18 @@ void PDBFileParser::ParseTitle()
sort(revdats.begin(), revdats.end()); sort(revdats.begin(), revdats.end());
for (auto &revdat : revdats) for (auto &revdat : revdats)
{ {
getCategory("database_PDB_rev")->emplace({{"num", revdat.revNum}, {"date", revdat.date}, {"date_original", revdat.dateOriginal}, {"replaces", revdat.replaces}, {"mod_type", revdat.modType}}); getCategory("database_PDB_rev")->emplace({{"num", revdat.revNum},
{"date", revdat.date},
{"date_original", revdat.dateOriginal},
{"replaces", revdat.replaces},
{"mod_type", revdat.modType}});
for (auto &type : revdat.types) for (auto &type : revdat.types)
{ {
if (type.empty()) if (type.empty())
continue; continue;
getCategory("database_PDB_rev_record")->emplace({{"rev_num", revdat.revNum}, {"type", type}}); getCategory("database_PDB_rev_record")->emplace({{"rev_num", revdat.revNum},
{"type", type}});
} }
} }
//*/ //*/
...@@ -2036,7 +2044,10 @@ void PDBFileParser::ParseRemarks() ...@@ -2036,7 +2044,10 @@ void PDBFileParser::ParseRemarks()
if (desc == "NULL") if (desc == "NULL")
desc.clear(); desc.clear();
getCategory("exptl_crystal")->emplace({{"id", 1}, {"density_Matthews", iequals(density_Matthews, "NULL") ? "" : density_Matthews}, {"density_percent_sol", iequals(densityPercentSol, "NULL") ? "" : densityPercentSol}, {"description", desc}}); getCategory("exptl_crystal")->emplace({{"id", 1},
{"density_Matthews", iequals(density_Matthews, "NULL") ? "" : density_Matthews},
{"density_percent_sol", iequals(densityPercentSol, "NULL") ? "" : densityPercentSol},
{"description", desc}});
// now try to parse the conditions // now try to parse the conditions
const std::regex rx3(R"(TEMPERATURE +(\d+)K)"), rx4(R"(PH *(?:: *)?(\d+(?:\.\d+)?))") /*, rx5(R"(\b(\d+)C\b)")*/; const std::regex rx3(R"(TEMPERATURE +(\d+)K)"), rx4(R"(PH *(?:: *)?(\d+(?:\.\d+)?))") /*, rx5(R"(\b(\d+)C\b)")*/;
...@@ -2065,7 +2076,11 @@ void PDBFileParser::ParseRemarks() ...@@ -2065,7 +2076,11 @@ void PDBFileParser::ParseRemarks()
if (not(method.empty() and temp.empty() and ph.empty() and (conditions.empty() or conditions == "NULL"))) if (not(method.empty() and temp.empty() and ph.empty() and (conditions.empty() or conditions == "NULL")))
{ {
getCategory("exptl_crystal_grow")->emplace({{"crystal_id", 1}, {"method", method}, {"temp", temp}, {"pH", ph}, {"pdbx_details", conditions}}); getCategory("exptl_crystal_grow")->emplace({{"crystal_id", 1},
{"method", method},
{"temp", temp},
{"pH", ph},
{"pdbx_details", conditions}});
} }
break; break;
...@@ -2283,7 +2298,21 @@ void PDBFileParser::ParseRemarks() ...@@ -2283,7 +2298,21 @@ void PDBFileParser::ParseRemarks()
std::string distance = vF(63, 71); std::string distance = vF(63, 71);
getCategory("pdbx_validate_close_contact")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", 1}, {"auth_atom_id_1", atom1}, {"auth_asym_id_1", std::string{chain1}}, {"auth_comp_id_1", res1}, {"auth_seq_id_1", seq1}, {"PDB_ins_code_1", iCode1}, {"label_alt_id_1", alt1}, {"auth_atom_id_2", atom2}, {"auth_asym_id_2", std::string{chain2}}, {"auth_comp_id_2", res2}, {"auth_seq_id_2", seq2}, {"PDB_ins_code_2", iCode2}, {"label_alt_id_2", alt2}, {"dist", distance}}); getCategory("pdbx_validate_close_contact")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", 1},
{"auth_atom_id_1", atom1},
{"auth_asym_id_1", std::string{chain1}},
{"auth_comp_id_1", res1},
{"auth_seq_id_1", seq1},
{"PDB_ins_code_1", iCode1},
{"label_alt_id_1", alt1},
{"auth_atom_id_2", atom2},
{"auth_asym_id_2", std::string{chain2}},
{"auth_comp_id_2", res2},
{"auth_seq_id_2", seq2},
{"PDB_ins_code_2", iCode2},
{"label_alt_id_2", alt2},
{"dist", distance}});
} }
break; break;
} }
...@@ -2320,7 +2349,12 @@ void PDBFileParser::ParseRemarks() ...@@ -2320,7 +2349,12 @@ void PDBFileParser::ParseRemarks()
std::string distance = vF(63, 71); std::string distance = vF(63, 71);
getCategory("pdbx_validate_symm_contact")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", 1}, {"auth_atom_id_1", atom1}, {"auth_asym_id_1", std::string{chain1}}, {"auth_comp_id_1", res1}, {"auth_seq_id_1", seq1}, getCategory("pdbx_validate_symm_contact")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", 1},
{"auth_atom_id_1", atom1},
{"auth_asym_id_1", std::string{chain1}},
{"auth_comp_id_1", res1},
{"auth_seq_id_1", seq1},
// { "PDB_ins_code_1", "" }, // { "PDB_ins_code_1", "" },
// { "label_alt_id_1", "" }, // { "label_alt_id_1", "" },
{"site_symmetry_1", "1_555"}, {"site_symmetry_1", "1_555"},
...@@ -2371,7 +2405,21 @@ void PDBFileParser::ParseRemarks() ...@@ -2371,7 +2405,21 @@ void PDBFileParser::ParseRemarks()
if (iCode2 == " ") if (iCode2 == " ")
iCode2.clear(); iCode2.clear();
getCategory("pdbx_validate_rmsd_bond")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", model ? model : 1}, {"auth_atom_id_1", atm1}, {"auth_asym_id_1", chainID1}, {"auth_comp_id_1", resNam1}, {"auth_seq_id_1", seqNum1}, {"PDB_ins_code_1", iCode1}, {"label_alt_id_1", alt1}, {"auth_atom_id_2", atm2}, {"auth_asym_id_2", chainID2}, {"auth_comp_id_2", resNam2}, {"auth_seq_id_2", seqNum2}, {"PDB_ins_code_2", iCode2}, {"label_alt_id_2", alt2}, {"bond_deviation", deviation}}); getCategory("pdbx_validate_rmsd_bond")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", model ? model : 1},
{"auth_atom_id_1", atm1},
{"auth_asym_id_1", chainID1},
{"auth_comp_id_1", resNam1},
{"auth_seq_id_1", seqNum1},
{"PDB_ins_code_1", iCode1},
{"label_alt_id_1", alt1},
{"auth_atom_id_2", atm2},
{"auth_asym_id_2", chainID2},
{"auth_comp_id_2", resNam2},
{"auth_seq_id_2", seqNum2},
{"PDB_ins_code_2", iCode2},
{"label_alt_id_2", alt2},
{"bond_deviation", deviation}});
} }
break; break;
...@@ -2403,7 +2451,24 @@ void PDBFileParser::ParseRemarks() ...@@ -2403,7 +2451,24 @@ void PDBFileParser::ParseRemarks()
if (deviation == "*****") if (deviation == "*****")
deviation.clear(); deviation.clear();
getCategory("pdbx_validate_rmsd_angle")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", model ? model : 1}, {"auth_atom_id_1", atoms[0]}, {"auth_asym_id_1", chainID}, {"auth_comp_id_1", resNam}, {"auth_seq_id_1", seqNum}, {"PDB_ins_code_1", iCode}, {"auth_atom_id_2", atoms[1]}, {"auth_asym_id_2", chainID}, {"auth_comp_id_2", resNam}, {"auth_seq_id_2", seqNum}, {"PDB_ins_code_2", iCode}, {"auth_atom_id_3", atoms[2]}, {"auth_asym_id_3", chainID}, {"auth_comp_id_3", resNam}, {"auth_seq_id_3", seqNum}, {"PDB_ins_code_3", iCode}, {"angle_deviation", deviation}}); getCategory("pdbx_validate_rmsd_angle")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", model ? model : 1},
{"auth_atom_id_1", atoms[0]},
{"auth_asym_id_1", chainID},
{"auth_comp_id_1", resNam},
{"auth_seq_id_1", seqNum},
{"PDB_ins_code_1", iCode},
{"auth_atom_id_2", atoms[1]},
{"auth_asym_id_2", chainID},
{"auth_comp_id_2", resNam},
{"auth_seq_id_2", seqNum},
{"PDB_ins_code_2", iCode},
{"auth_atom_id_3", atoms[2]},
{"auth_asym_id_3", chainID},
{"auth_comp_id_3", resNam},
{"auth_seq_id_3", seqNum},
{"PDB_ins_code_3", iCode},
{"angle_deviation", deviation}});
} }
break; break;
...@@ -2432,7 +2497,14 @@ void PDBFileParser::ParseRemarks() ...@@ -2432,7 +2497,14 @@ void PDBFileParser::ParseRemarks()
std::string psi = vF(27, 35); std::string psi = vF(27, 35);
std::string phi = vF(37, 45); std::string phi = vF(37, 45);
getCategory("pdbx_validate_torsion")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", model ? model : 1}, {"auth_comp_id", resNam}, {"auth_asym_id", chainID}, {"auth_seq_id", seqNum}, {"PDB_ins_code", iCode}, {"phi", phi}, {"psi", psi}}); getCategory("pdbx_validate_torsion")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", model ? model : 1},
{"auth_comp_id", resNam},
{"auth_asym_id", chainID},
{"auth_seq_id", seqNum},
{"PDB_ins_code", iCode},
{"phi", phi},
{"psi", psi}});
} }
break; break;
...@@ -2463,7 +2535,17 @@ void PDBFileParser::ParseRemarks() ...@@ -2463,7 +2535,17 @@ void PDBFileParser::ParseRemarks()
std::string omega = vF(54, 60); std::string omega = vF(54, 60);
getCategory("pdbx_validate_peptide_omega")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", model ? model : 1}, {"auth_comp_id_1", resNam1}, {"auth_asym_id_1", chainID1}, {"auth_seq_id_1", seqNum1}, {"PDB_ins_code_1", iCode1}, {"auth_comp_id_2", resNam2}, {"auth_asym_id_2", chainID2}, {"auth_seq_id_2", seqNum2}, {"PDB_ins_code_2", iCode2}, {"omega", omega}}); getCategory("pdbx_validate_peptide_omega")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", model ? model : 1},
{"auth_comp_id_1", resNam1},
{"auth_asym_id_1", chainID1},
{"auth_seq_id_1", seqNum1},
{"PDB_ins_code_1", iCode1},
{"auth_comp_id_2", resNam2},
{"auth_asym_id_2", chainID2},
{"auth_seq_id_2", seqNum2},
{"PDB_ins_code_2", iCode2},
{"omega", omega}});
} }
break; break;
...@@ -2486,7 +2568,14 @@ void PDBFileParser::ParseRemarks() ...@@ -2486,7 +2568,14 @@ void PDBFileParser::ParseRemarks()
std::string rmsd = vF(32, 36); std::string rmsd = vF(32, 36);
std::string type = vS(41); std::string type = vS(41);
getCategory("pdbx_validate_planes")->emplace({{"id", std::to_string(++id)}, {"PDB_model_num", model ? model : 1}, {"auth_comp_id", resNam}, {"auth_asym_id", chainID}, {"auth_seq_id", seqNum}, {"PDB_ins_code", iCode}, {"rmsd", rmsd}, {"type", type}}); getCategory("pdbx_validate_planes")->emplace({{"id", std::to_string(++id)},
{"PDB_model_num", model ? model : 1},
{"auth_comp_id", resNam},
{"auth_asym_id", chainID},
{"auth_seq_id", seqNum},
{"PDB_ins_code", iCode},
{"rmsd", rmsd},
{"type", type}});
} }
break; break;
...@@ -2566,7 +2655,13 @@ void PDBFileParser::ParseRemarks() ...@@ -2566,7 +2655,13 @@ void PDBFileParser::ParseRemarks()
throw std::runtime_error("Invalid REMARK 800, no SITE record for id " + id); throw std::runtime_error("Invalid REMARK 800, no SITE record for id " + id);
// next record, store what we have // next record, store what we have
getCategory("struct_site")->emplace({{"id", id}, {"details", desc}, {"pdbx_auth_asym_id", pdbxAuthAsymID}, {"pdbx_auth_comp_id", pdbxAuthCompID}, {"pdbx_auth_seq_id", pdbxAuthSeqID}, {"pdbx_num_residues", site->vI(16, 17)}, {"pdbx_evidence_code", evidence}}); getCategory("struct_site")->emplace({{"id", id},
{"details", desc},
{"pdbx_auth_asym_id", pdbxAuthAsymID},
{"pdbx_auth_comp_id", pdbxAuthCompID},
{"pdbx_auth_seq_id", pdbxAuthSeqID},
{"pdbx_num_residues", site->vI(16, 17)},
{"pdbx_evidence_code", evidence}});
}; };
for (; mRec->is("REMARK 800"); GetNextRecord()) for (; mRec->is("REMARK 800"); GetNextRecord())
...@@ -2680,7 +2775,8 @@ void PDBFileParser::ParseRemarks() ...@@ -2680,7 +2775,8 @@ void PDBFileParser::ParseRemarks()
GetNextRecord(); GetNextRecord();
} }
getCategory("pdbx_database_remark")->emplace({{"id", remarkNr}, {"text", s.str()}}); getCategory("pdbx_database_remark")->emplace({{"id", remarkNr},
{"text", s.str()}});
break; break;
} }
...@@ -2694,7 +2790,10 @@ void PDBFileParser::ParseRemarks() ...@@ -2694,7 +2790,10 @@ void PDBFileParser::ParseRemarks()
if (not(compoundDetails.empty() and sequenceDetails.empty() and sourceDetails.empty())) if (not(compoundDetails.empty() and sequenceDetails.empty() and sourceDetails.empty()))
{ {
getCategory("pdbx_entry_details")->emplace({{"entry_id", mStructureID}, {"compound_details", compoundDetails}, {"sequence_details", sequenceDetails}, {"source_details", sourceDetails}}); getCategory("pdbx_entry_details")->emplace({{"entry_id", mStructureID},
{"compound_details", compoundDetails},
{"sequence_details", sequenceDetails},
{"source_details", sourceDetails}});
} }
// store remark 200 info (special case) // store remark 200 info (special case)
...@@ -2774,7 +2873,10 @@ void PDBFileParser::ParseRemark200() ...@@ -2774,7 +2873,10 @@ void PDBFileParser::ParseRemark200()
if (mRemark200[sw.b].empty()) if (mRemark200[sw.b].empty())
continue; continue;
getCategory("software")->emplace({{"name", mRemark200[sw.b]}, {"classification", sw.a}, {"version", "."}, {"pdbx_ordinal", mNextSoftwareOrd++}}); getCategory("software")->emplace({{"name", mRemark200[sw.b]},
{"classification", sw.a},
{"version", "."},
{"pdbx_ordinal", mNextSoftwareOrd++}});
} }
std::string scatteringType; std::string scatteringType;
...@@ -2812,10 +2914,19 @@ void PDBFileParser::ParseRemark200() ...@@ -2812,10 +2914,19 @@ void PDBFileParser::ParseRemark200()
collectionDate.clear(); collectionDate.clear();
} }
getCategory("diffrn_detector")->emplace({{"diffrn_id", diffrnNr}, {"detector", rm200("DETECTOR TYPE", diffrnNr)}, {"type", rm200("DETECTOR MANUFACTURER", diffrnNr)}, {"pdbx_collection_date", collectionDate}, {"details", rm200("OPTICS", diffrnNr)}}); getCategory("diffrn_detector")->emplace({{"diffrn_id", diffrnNr},
{"detector", rm200("DETECTOR TYPE", diffrnNr)},
{"type", rm200("DETECTOR MANUFACTURER", diffrnNr)},
{"pdbx_collection_date", collectionDate},
{"details", rm200("OPTICS", diffrnNr)}});
if (inRM200({"MONOCHROMATIC OR LAUE (M/L)", "MONOCHROMATOR", "DIFFRACTION PROTOCOL"}) or not scatteringType.empty()) if (inRM200({"MONOCHROMATIC OR LAUE (M/L)", "MONOCHROMATOR", "DIFFRACTION PROTOCOL"}) or not scatteringType.empty())
getCategory("diffrn_radiation")->emplace({{"diffrn_id", diffrnNr}, {"wavelength_id", 1}, {"pdbx_monochromatic_or_laue_m_l", rm200("MONOCHROMATIC OR LAUE (M/L)", diffrnNr)}, {"monochromator", rm200("MONOCHROMATOR", diffrnNr)}, {"pdbx_diffrn_protocol", rm200("DIFFRACTION PROTOCOL", diffrnNr)}, {"pdbx_scattering_type", scatteringType}}); getCategory("diffrn_radiation")->emplace({{"diffrn_id", diffrnNr},
{"wavelength_id", 1},
{"pdbx_monochromatic_or_laue_m_l", rm200("MONOCHROMATIC OR LAUE (M/L)", diffrnNr)},
{"monochromator", rm200("MONOCHROMATOR", diffrnNr)},
{"pdbx_diffrn_protocol", rm200("DIFFRACTION PROTOCOL", diffrnNr)},
{"pdbx_scattering_type", scatteringType}});
std::vector<std::string> wavelengths; std::vector<std::string> wavelengths;
std::string wl = rm200("WAVELENGTH OR RANGE (A)", diffrnNr); std::string wl = rm200("WAVELENGTH OR RANGE (A)", diffrnNr);
...@@ -2856,7 +2967,9 @@ void PDBFileParser::ParseRemark200() ...@@ -2856,7 +2967,9 @@ void PDBFileParser::ParseRemark200()
if (ba::ends_with(wl, "A")) if (ba::ends_with(wl, "A"))
wl.erase(wl.length() - 1, 1); wl.erase(wl.length() - 1, 1);
getCategory("diffrn_radiation_wavelength")->emplace({{"id", wavelengthNr++}, {"wavelength", wl.empty() ? "." : wl}, {"wt", "1.0"}}); getCategory("diffrn_radiation_wavelength")->emplace({{"id", wavelengthNr++},
{"wavelength", wl.empty() ? "." : wl},
{"wt", "1.0"}});
} }
if (inRM200({"METHOD USED TO DETERMINE THE STRUCTURE", "STARTING MODEL"})) if (inRM200({"METHOD USED TO DETERMINE THE STRUCTURE", "STARTING MODEL"}))
...@@ -2899,7 +3012,15 @@ void PDBFileParser::ParseRemark200() ...@@ -2899,7 +3012,15 @@ void PDBFileParser::ParseRemark200()
if (inRM200({"HIGHEST RESOLUTION SHELL, RANGE HIGH (A)"})) // that one field is mandatory... if (inRM200({"HIGHEST RESOLUTION SHELL, RANGE HIGH (A)"})) // that one field is mandatory...
{ {
getCategory("reflns_shell")->emplace({{"d_res_high", mRemark200["HIGHEST RESOLUTION SHELL, RANGE HIGH (A)"]}, {"d_res_low", mRemark200["HIGHEST RESOLUTION SHELL, RANGE LOW (A)"]}, {"percent_possible_all", mRemark200["COMPLETENESS FOR SHELL (%)"]}, {"Rmerge_I_obs", mRemark200["R MERGE FOR SHELL (I)"]}, {"pdbx_Rsym_value", mRemark200["R SYM FOR SHELL (I)"]}, {"meanI_over_sigI_obs", mRemark200["<I/SIGMA(I)> FOR SHELL"]}, {"pdbx_redundancy", mRemark200["DATA REDUNDANCY IN SHELL"]}, {"pdbx_ordinal", 1}, {"pdbx_diffrn_id", 1}}); getCategory("reflns_shell")->emplace({{"d_res_high", mRemark200["HIGHEST RESOLUTION SHELL, RANGE HIGH (A)"]},
{"d_res_low", mRemark200["HIGHEST RESOLUTION SHELL, RANGE LOW (A)"]},
{"percent_possible_all", mRemark200["COMPLETENESS FOR SHELL (%)"]},
{"Rmerge_I_obs", mRemark200["R MERGE FOR SHELL (I)"]},
{"pdbx_Rsym_value", mRemark200["R SYM FOR SHELL (I)"]},
{"meanI_over_sigI_obs", mRemark200["<I/SIGMA(I)> FOR SHELL"]},
{"pdbx_redundancy", mRemark200["DATA REDUNDANCY IN SHELL"]},
{"pdbx_ordinal", 1},
{"pdbx_diffrn_id", 1}});
} }
else if (inRM200({"HIGHEST RESOLUTION SHELL, RANGE LOW (A)", "COMPLETENESS FOR SHELL (%)", else if (inRM200({"HIGHEST RESOLUTION SHELL, RANGE LOW (A)", "COMPLETENESS FOR SHELL (%)",
"R MERGE FOR SHELL (I)", "R SYM FOR SHELL (I)", "<I/SIGMA(I)> FOR SHELL", "DATA REDUNDANCY IN SHELL"})) "R MERGE FOR SHELL (I)", "R SYM FOR SHELL (I)", "<I/SIGMA(I)> FOR SHELL", "DATA REDUNDANCY IN SHELL"}))
...@@ -3091,7 +3212,11 @@ void PDBFileParser::ParseRemark350() ...@@ -3091,7 +3212,11 @@ void PDBFileParser::ParseRemark350()
else else
details = "author_and_software_defined_assembly"; details = "author_and_software_defined_assembly";
getCategory("pdbx_struct_assembly")->emplace({{"id", biomolecule}, {"details", details}, {"method_details", values["SOFTWARE USED"]}, {"oligomeric_details", oligomer}, {"oligomeric_count", count > 0 ? std::to_string(count) : ""}}); getCategory("pdbx_struct_assembly")->emplace({{"id", biomolecule},
{"details", details},
{"method_details", values["SOFTWARE USED"]},
{"oligomeric_details", oligomer},
{"oligomeric_count", count > 0 ? std::to_string(count) : ""}});
auto cat = getCategory("pdbx_struct_assembly_prop"); auto cat = getCategory("pdbx_struct_assembly_prop");
...@@ -3115,21 +3240,23 @@ void PDBFileParser::ParseRemark350() ...@@ -3115,21 +3240,23 @@ void PDBFileParser::ParseRemark350()
boost::format fmt("%12.10f"); boost::format fmt("%12.10f");
getCategory("pdbx_struct_oper_list")->emplace({{"id", operID}, {"type", mat == std::vector<double>{1, 0, 0, 0, 1, 0, 0, 0, 1} and vec == std::vector<double>{0, 0, 0} ? "identity operation" : "crystal symmetry operation"}, getCategory("pdbx_struct_oper_list")->emplace({
// { "name", "" }, {"id", operID},
// { "symmetryOperation", "" }, {"type", mat == std::vector<double>{1, 0, 0, 0, 1, 0, 0, 0, 1} and vec == std::vector<double>{0, 0, 0} ? "identity operation" : "crystal symmetry operation"},
{"matrix[1][1]", (fmt % mat[0]).str()}, // { "name", "" },
{"matrix[1][2]", (fmt % mat[1]).str()}, // { "symmetryOperation", "" },
{"matrix[1][3]", (fmt % mat[2]).str()}, {"matrix[1][1]", (fmt % mat[0]).str()},
{"vector[1]", (fmt % vec[0]).str()}, {"matrix[1][2]", (fmt % mat[1]).str()},
{"matrix[2][1]", (fmt % mat[3]).str()}, {"matrix[1][3]", (fmt % mat[2]).str()},
{"matrix[2][2]", (fmt % mat[4]).str()}, {"vector[1]", (fmt % vec[0]).str()},
{"matrix[2][3]", (fmt % mat[5]).str()}, {"matrix[2][1]", (fmt % mat[3]).str()},
{"vector[2]", (fmt % vec[1]).str()}, {"matrix[2][2]", (fmt % mat[4]).str()},
{"matrix[3][1]", (fmt % mat[6]).str()}, {"matrix[2][3]", (fmt % mat[5]).str()},
{"matrix[3][2]", (fmt % mat[7]).str()}, {"vector[2]", (fmt % vec[1]).str()},
{"matrix[3][3]", (fmt % mat[8]).str()}, {"matrix[3][1]", (fmt % mat[6]).str()},
{"vector[3]", (fmt % vec[2]).str()}}); {"matrix[3][2]", (fmt % mat[7]).str()},
{"matrix[3][3]", (fmt % mat[8]).str()},
{"vector[3]", (fmt % vec[2]).str()}});
mat.clear(); mat.clear();
vec.clear(); vec.clear();
...@@ -3140,7 +3267,9 @@ void PDBFileParser::ParseRemark350() ...@@ -3140,7 +3267,9 @@ void PDBFileParser::ParseRemark350()
if (not(vec.empty() and mat.empty())) if (not(vec.empty() and mat.empty()))
throw std::runtime_error("Invalid REMARK 350"); throw std::runtime_error("Invalid REMARK 350");
getCategory("pdbx_struct_assembly_gen")->emplace({{"assembly_id", biomolecule}, {"oper_expression", ba::join(operExpression, ",")}, {"asym_id_list", ba::join(asymIdList, ",")}}); getCategory("pdbx_struct_assembly_gen")->emplace({{"assembly_id", biomolecule},
{"oper_expression", ba::join(operExpression, ",")},
{"asym_id_list", ba::join(asymIdList, ",")}});
biomolecule = stoi(m[1].str()); biomolecule = stoi(m[1].str());
asymIdList.clear(); asymIdList.clear();
...@@ -3154,7 +3283,9 @@ void PDBFileParser::ParseRemark350() ...@@ -3154,7 +3283,9 @@ void PDBFileParser::ParseRemark350()
if (not operExpression.empty()) if (not operExpression.empty())
{ {
getCategory("pdbx_struct_assembly_gen")->emplace({{"assembly_id", biomolecule}, {"oper_expression", ba::join(operExpression, ",")}, {"asym_id_list", ba::join(asymIdList, ",")}}); getCategory("pdbx_struct_assembly_gen")->emplace({{"assembly_id", biomolecule},
{"oper_expression", ba::join(operExpression, ",")},
{"asym_id_list", ba::join(asymIdList, ",")}});
} }
mRec = saved; mRec = saved;
...@@ -3641,10 +3772,11 @@ void PDBFileParser::ConstructEntities() ...@@ -3641,10 +3772,11 @@ void PDBFileParser::ConstructEntities()
mAsymID2EntityID[asymID] = entityID; mAsymID2EntityID[asymID] = entityID;
getCategory("struct_asym")->emplace({ getCategory("struct_asym")->emplace({
{"id", asymID}, {"pdbx_blank_PDB_chainid_flag", chain.mDbref.chainID == ' ' ? "Y" : "N"}, {"id", asymID},
// pdbx_modified {"pdbx_blank_PDB_chainid_flag", chain.mDbref.chainID == ' ' ? "Y" : "N"},
// pdbx_modified
{"entity_id", entityID}, {"entity_id", entityID},
// details // details
}); });
int seqNr = 1; int seqNr = 1;
...@@ -3708,7 +3840,32 @@ void PDBFileParser::ConstructEntities() ...@@ -3708,7 +3840,32 @@ void PDBFileParser::ConstructEntities()
{ {
srcMethod = "man"; srcMethod = "man";
getCategory("entity_src_gen")->emplace({{"entity_id", mMolID2EntityID[cmp.mMolID]}, {"pdbx_src_id", structRefID}, {"gene_src_common_name", cmp.mSource["ORGANISM_COMMON"]}, {"pdbx_gene_src_gene", cmp.mSource["GENE"]}, {"gene_src_strain", cmp.mSource["STRAIN"]}, {"gene_src_tissue", cmp.mSource["TISSUE"]}, {"gene_src_tissue_fraction", cmp.mSource["TISSUE_FRACTION"]}, {"pdbx_gene_src_cell_line", cmp.mSource["CELL_LINE"]}, {"pdbx_gene_src_organelle", cmp.mSource["ORGANELLE"]}, {"pdbx_gene_src_cell", cmp.mSource["CELL"]}, {"pdbx_gene_src_cellular_location", cmp.mSource["CELLULAR_LOCATION"]}, {"host_org_common_name", cmp.mSource["EXPRESSION_SYSTEM_COMMON"]}, {"pdbx_gene_src_scientific_name", cmp.mSource["ORGANISM_SCIENTIFIC"]}, {"pdbx_gene_src_ncbi_taxonomy_id", cmp.mSource["ORGANISM_TAXID"]}, {"pdbx_host_org_scientific_name", cmp.mSource["EXPRESSION_SYSTEM"]}, {"pdbx_host_org_ncbi_taxonomy_id", cmp.mSource["EXPRESSION_SYSTEM_TAXID"]}, {"pdbx_host_org_strain", cmp.mSource["EXPRESSION_SYSTEM_STRAIN"]}, {"pdbx_host_org_variant", cmp.mSource["EXPRESSION_SYSTEM_VARIANT"]}, {"pdbx_host_org_cell_line", cmp.mSource["EXPRESSION_SYSTEM_CELL_LINE"]}, {"pdbx_host_org_cellular_location", cmp.mSource["EXPRESSION_SYSTEM_CELLULAR_LOCATION"]}, {"pdbx_host_org_vector_type", cmp.mSource["EXPRESSION_SYSTEM_VECTOR_TYPE"]}, {"pdbx_host_org_vector", cmp.mSource["EXPRESSION_SYSTEM_VECTOR"]}, {"pdbx_host_org_gene", cmp.mSource["EXPRESSION_SYSTEM_GENE"]}, {"plasmid_name", cmp.mSource["EXPRESSION_SYSTEM_PLASMID"]}, {"pdbx_description", cmp.mSource["OTHER_DETAILS"]}}); getCategory("entity_src_gen")->emplace({
{"entity_id", mMolID2EntityID[cmp.mMolID]},
{"pdbx_src_id", structRefID},
{"gene_src_common_name", cmp.mSource["ORGANISM_COMMON"]},
{"pdbx_gene_src_gene", cmp.mSource["GENE"]},
{"gene_src_strain", cmp.mSource["STRAIN"]},
{"gene_src_tissue", cmp.mSource["TISSUE"]},
{"gene_src_tissue_fraction", cmp.mSource["TISSUE_FRACTION"]},
{"pdbx_gene_src_cell_line", cmp.mSource["CELL_LINE"]},
{"pdbx_gene_src_organelle", cmp.mSource["ORGANELLE"]},
{"pdbx_gene_src_cell", cmp.mSource["CELL"]},
{"pdbx_gene_src_cellular_location", cmp.mSource["CELLULAR_LOCATION"]},
{"host_org_common_name", cmp.mSource["EXPRESSION_SYSTEM_COMMON"]},
{"pdbx_gene_src_scientific_name", cmp.mSource["ORGANISM_SCIENTIFIC"]},
{"pdbx_gene_src_ncbi_taxonomy_id", cmp.mSource["ORGANISM_TAXID"]},
{"pdbx_host_org_scientific_name", cmp.mSource["EXPRESSION_SYSTEM"]},
{"pdbx_host_org_ncbi_taxonomy_id", cmp.mSource["EXPRESSION_SYSTEM_TAXID"]},
{"pdbx_host_org_strain", cmp.mSource["EXPRESSION_SYSTEM_STRAIN"]},
{"pdbx_host_org_variant", cmp.mSource["EXPRESSION_SYSTEM_VARIANT"]},
{"pdbx_host_org_cell_line", cmp.mSource["EXPRESSION_SYSTEM_CELL_LINE"]},
{"pdbx_host_org_cellular_location", cmp.mSource["EXPRESSION_SYSTEM_CELLULAR_LOCATION"]},
{"pdbx_host_org_vector_type", cmp.mSource["EXPRESSION_SYSTEM_VECTOR_TYPE"]},
{"pdbx_host_org_vector", cmp.mSource["EXPRESSION_SYSTEM_VECTOR"]},
{"pdbx_host_org_gene", cmp.mSource["EXPRESSION_SYSTEM_GENE"]},
{"plasmid_name", cmp.mSource["EXPRESSION_SYSTEM_PLASMID"]},
{"pdbx_description", cmp.mSource["OTHER_DETAILS"]}});
} }
else if (not cmp.mSource["ORGANISM_SCIENTIFIC"].empty()) else if (not cmp.mSource["ORGANISM_SCIENTIFIC"].empty())
{ {
...@@ -3741,7 +3898,10 @@ void PDBFileParser::ConstructEntities() ...@@ -3741,7 +3898,10 @@ void PDBFileParser::ConstructEntities()
if (not cmp.mInfo["SYNONYM"].empty()) if (not cmp.mInfo["SYNONYM"].empty())
{ {
getCategory("entity_name_com")->emplace({{"entity_id", mMolID2EntityID[cmp.mMolID]}, {"name", cmp.mInfo["SYNONYM"]}}); getCategory("entity_name_com")->emplace({
{"entity_id", mMolID2EntityID[cmp.mMolID]},
{"name", cmp.mInfo["SYNONYM"]}
});
} }
std::string desc = cmp.mInfo["MOLECULE"]; std::string desc = cmp.mInfo["MOLECULE"];
...@@ -3761,7 +3921,11 @@ void PDBFileParser::ConstructEntities() ...@@ -3761,7 +3921,11 @@ void PDBFileParser::ConstructEntities()
if (ci != mChains.end() and not ci->mDbref.dbIdCode.empty()) if (ci != mChains.end() and not ci->mDbref.dbIdCode.empty())
{ {
getCategory("struct_ref")->emplace({ getCategory("struct_ref")->emplace({
{"id", structRefID}, {"entity_id", mMolID2EntityID[cmp.mMolID]}, {"db_name", ci->mDbref.database}, {"db_code", ci->mDbref.dbIdCode}, {"pdbx_db_accession", ci->mDbref.dbAccession}, {"id", structRefID},
{"entity_id", mMolID2EntityID[cmp.mMolID]},
{"db_name", ci->mDbref.database},
{"db_code", ci->mDbref.dbIdCode},
{"pdbx_db_accession", ci->mDbref.dbAccession},
// { "pdbx_align_begin", ci->mDbref.dbSeqBegin } // { "pdbx_align_begin", ci->mDbref.dbSeqBegin }
}); });
} }
...@@ -3810,7 +3974,23 @@ void PDBFileParser::ConstructEntities() ...@@ -3810,7 +3974,23 @@ void PDBFileParser::ConstructEntities()
{ {
} }
getCategory("struct_ref_seq")->emplace({{"align_id", structRefSeqAlignID}, {"ref_id", structRefID}, {"pdbx_PDB_id_code", dbref.PDBIDCode}, {"pdbx_strand_id", std::string{chain.mDbref.chainID}}, {"seq_align_beg", seqAlignBeg}, {"pdbx_seq_align_beg_ins_code", insToStr(dbref.insertBegin)}, {"seq_align_end", seqAlignEnd}, {"pdbx_seq_align_end_ins_code", insToStr(dbref.insertEnd)}, {"pdbx_db_accession", dbref.dbAccession}, {"db_align_beg", dbref.dbSeqBegin}, {"pdbx_db_align_beg_ins_code", insToStr(dbref.dbinsBeg)}, {"db_align_end", dbref.dbSeqEnd}, {"pdbx_db_align_end_ins_code", insToStr(dbref.dbinsEnd)}, {"pdbx_auth_seq_align_beg", dbref.seqBegin}, {"pdbx_auth_seq_align_end", dbref.seqEnd}}); getCategory("struct_ref_seq")->emplace({
{"align_id", structRefSeqAlignID},
{"ref_id", structRefID},
{"pdbx_PDB_id_code", dbref.PDBIDCode},
{"pdbx_strand_id", std::string{chain.mDbref.chainID}},
{"seq_align_beg", seqAlignBeg},
{"pdbx_seq_align_beg_ins_code", insToStr(dbref.insertBegin)},
{"seq_align_end", seqAlignEnd},
{"pdbx_seq_align_end_ins_code", insToStr(dbref.insertEnd)},
{"pdbx_db_accession", dbref.dbAccession},
{"db_align_beg", dbref.dbSeqBegin},
{"pdbx_db_align_beg_ins_code", insToStr(dbref.dbinsBeg)},
{"db_align_end", dbref.dbSeqEnd},
{"pdbx_db_align_end_ins_code", insToStr(dbref.dbinsEnd)},
{"pdbx_auth_seq_align_beg", dbref.seqBegin},
{"pdbx_auth_seq_align_end", dbref.seqEnd}
});
// write the struct_ref_seq_dif // write the struct_ref_seq_dif
for (auto &seqadv : mSeqadvs) for (auto &seqadv : mSeqadvs)
...@@ -3832,7 +4012,21 @@ void PDBFileParser::ConstructEntities() ...@@ -3832,7 +4012,21 @@ void PDBFileParser::ConstructEntities()
seqNum = std::to_string(labelSeq); seqNum = std::to_string(labelSeq);
getCategory("struct_ref_seq_dif")->emplace({{"align_id", structRefSeqAlignID}, {"pdbx_PDB_id_code", dbref.PDBIDCode}, {"mon_id", seqadv.resName}, {"pdbx_pdb_strand_id", seqadv.chainID}, {"seq_num", seqNum}, {"pdbx_pdb_ins_code", seqadv.iCode == ' ' ? std::string{} : std::string{seqadv.iCode}}, {"pdbx_seq_db_name", seqadv.database}, {"pdbx_seq_db_accession_code", seqadv.dbAccession}, {"db_mon_id", seqadv.dbRes}, {"pdbx_seq_db_seq_num", seqadv.dbSeq}, {"details", seqadv.conflict}, {"pdbx_auth_seq_num", seqadv.seqNum}, {"pdbx_ordinal", ++mPdbxDifOrdinal}}); getCategory("struct_ref_seq_dif")->emplace({
{"align_id", structRefSeqAlignID},
{"pdbx_PDB_id_code", dbref.PDBIDCode},
{"mon_id", seqadv.resName},
{"pdbx_pdb_strand_id", seqadv.chainID},
{"seq_num", seqNum},
{"pdbx_pdb_ins_code", seqadv.iCode == ' ' ? std::string{} : std::string{seqadv.iCode}},
{"pdbx_seq_db_name", seqadv.database},
{"pdbx_seq_db_accession_code", seqadv.dbAccession},
{"db_mon_id", seqadv.dbRes},
{"pdbx_seq_db_seq_num", seqadv.dbSeq},
{"details", seqadv.conflict},
{"pdbx_auth_seq_num", seqadv.seqNum},
{"pdbx_ordinal", ++mPdbxDifOrdinal}
});
} }
} }
...@@ -3932,15 +4126,23 @@ void PDBFileParser::ConstructEntities() ...@@ -3932,15 +4126,23 @@ void PDBFileParser::ConstructEntities()
else if (mightBeDNA and not mightBePolyPeptide) else if (mightBeDNA and not mightBePolyPeptide)
type = "polyribonucleotide"; type = "polyribonucleotide";
getCategory("entity_poly")->emplace({{"entity_id", mMolID2EntityID[cmp.mMolID]}, {"pdbx_seq_one_letter_code", seq}, {"pdbx_seq_one_letter_code_can", seqCan}, {"nstd_monomer", (nstdMonomer ? "yes" : "no")}, {"pdbx_strand_id", ba::join(chains, ",")}, {"nstd_linkage", nonstandardLinkage ? "yes" : "no"}, {"type", type}}); getCategory("entity_poly")->emplace({{"entity_id", mMolID2EntityID[cmp.mMolID]},
{"pdbx_seq_one_letter_code", seq},
{"pdbx_seq_one_letter_code_can", seqCan},
{"nstd_monomer", (nstdMonomer ? "yes" : "no")},
{"pdbx_strand_id", ba::join(chains, ",")},
{"nstd_linkage", nonstandardLinkage ? "yes" : "no"},
{"type", type}});
} }
if (not(structTitle.empty() and structDescription.empty())) if (not(structTitle.empty() and structDescription.empty()))
{ {
getCategory("struct")->emplace({{"entry_id", mStructureID}, getCategory("struct")->emplace({
{"title", ba::join(structTitle, ", ")}, {"entry_id", mStructureID},
{"pdbx_descriptor", ba::join(structDescription, ", ")}, {"title", ba::join(structTitle, ", ")},
{"pdbx_model_type_details", mModelTypeDetails}}); {"pdbx_descriptor", ba::join(structDescription, ", ")},
{"pdbx_model_type_details", mModelTypeDetails}
});
} }
// build sugar trees first // build sugar trees first
...@@ -4026,7 +4228,9 @@ void PDBFileParser::ConstructEntities() ...@@ -4026,7 +4228,9 @@ void PDBFileParser::ConstructEntities()
std::string name = mHetnams[hetID]; std::string name = mHetnams[hetID];
if (name.empty() and hetID == mWaterHetID) if (name.empty() and hetID == mWaterHetID)
name = "water"; name = "water";
getCategory("pdbx_entity_nonpoly")->emplace({{"entity_id", entityID}, {"name", name}, {"comp_id", hetID}}); getCategory("pdbx_entity_nonpoly")->emplace({{"entity_id", entityID},
{"name", name},
{"comp_id", hetID}});
} }
// create an asym for this het/chain combo, if needed // create an asym for this het/chain combo, if needed
...@@ -4063,7 +4267,8 @@ void PDBFileParser::ConstructEntities() ...@@ -4063,7 +4267,8 @@ void PDBFileParser::ConstructEntities()
{ {
writtenAsyms.insert(asymID); writtenAsyms.insert(asymID);
getCategory("struct_asym")->emplace({ getCategory("struct_asym")->emplace({
{"id", asymID}, {"pdbx_blank_PDB_chainid_flag", het.chainID == ' ' ? "Y" : "N"}, {"id", asymID},
{"pdbx_blank_PDB_chainid_flag", het.chainID == ' ' ? "Y" : "N"},
// pdbx_modified // pdbx_modified
{"entity_id", mHet2EntityID[hetID]}, {"entity_id", mHet2EntityID[hetID]},
// details // details
...@@ -4078,12 +4283,18 @@ void PDBFileParser::ConstructEntities() ...@@ -4078,12 +4283,18 @@ void PDBFileParser::ConstructEntities()
if (iCode.empty()) if (iCode.empty())
iCode = {'.'}; iCode = {'.'};
getCategory("pdbx_nonpoly_scheme")->emplace({{"asym_id", asymID}, {"entity_id", mHet2EntityID[hetID]}, {"mon_id", hetID}, {"ndb_seq_num", seqNr}, {"pdb_seq_num", het.seqNum}, getCategory("pdbx_nonpoly_scheme")->emplace({
// { "auth_seq_num", het.seqNum }, // ???? {"asym_id", asymID},
{"pdb_mon_id", hetID}, {"entity_id", mHet2EntityID[hetID]},
// { "auth_mon_id", hetID }, {"mon_id", hetID},
{"pdb_strand_id", std::string{het.chainID}}, {"ndb_seq_num", seqNr},
{"pdb_ins_code", iCode}}); {"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}
});
// mapping needed? // mapping needed?
mChainSeq2AsymSeq[std::make_tuple(het.chainID, het.seqNum, het.iCode)] = std::make_tuple(asymID, seqNr, false); mChainSeq2AsymSeq[std::make_tuple(het.chainID, het.seqNum, het.iCode)] = std::make_tuple(asymID, seqNr, false);
...@@ -4113,7 +4324,18 @@ void PDBFileParser::ConstructEntities() ...@@ -4113,7 +4324,18 @@ void PDBFileParser::ConstructEntities()
continue; continue;
} }
getCategory("pdbx_struct_mod_residue")->emplace({{"id", modResID++}, {"label_asym_id", asymID}, {"label_seq_id", seq}, {"label_comp_id", resName}, {"auth_asym_id", std::string(1, chainID)}, {"auth_seq_id", seqNum}, {"auth_comp_id", resName}, {"PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}}, {"parent_comp_id", stdRes}, {"details", comment}}); getCategory("pdbx_struct_mod_residue")->emplace({
{"id", modResID++},
{"label_asym_id", asymID},
{"label_seq_id", seq},
{"label_comp_id", resName},
{"auth_asym_id", std::string(1, chainID)},
{"auth_seq_id", seqNum},
{"auth_comp_id", resName},
{"PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}},
{"parent_comp_id", stdRes},
{"details", comment}
});
modResSet.insert(resName); modResSet.insert(resName);
} }
...@@ -4162,7 +4384,12 @@ void PDBFileParser::ConstructEntities() ...@@ -4162,7 +4384,12 @@ void PDBFileParser::ConstructEntities()
if (modResSet.count(cc)) if (modResSet.count(cc))
nstd = "n"; nstd = "n";
getCategory("chem_comp")->emplace({{"id", cc}, {"name", name}, {"formula", formula}, {"formula_weight", formulaWeight}, {"mon_nstd_flag", nstd}, {"type", type}}); getCategory("chem_comp")->emplace({{"id", cc},
{"name", name},
{"formula", formula},
{"formula_weight", formulaWeight},
{"mon_nstd_flag", nstd},
{"type", type}});
} }
getCategory("chem_comp")->reorderByIndex(); getCategory("chem_comp")->reorderByIndex();
...@@ -4195,16 +4422,39 @@ void PDBFileParser::ConstructEntities() ...@@ -4195,16 +4422,39 @@ void PDBFileParser::ConstructEntities()
if (unobs.atoms.empty()) if (unobs.atoms.empty())
{ {
getCategory("pdbx_unobs_or_zero_occ_residues")->emplace({{"id", std::to_string(++idRes)}, {"polymer_flag", isPolymer ? "Y" : "N"}, {"occupancy_flag", 1}, {"PDB_model_num", unobs.modelNr ? unobs.modelNr : 1}, {"auth_asym_id", std::string{unobs.chain}}, {"auth_comp_id", unobs.res}, {"auth_seq_id", unobs.seq}, {"PDB_ins_code", unobs.iCode == ' ' ? "" : std::string{unobs.iCode}}, {"label_asym_id", asymID}, {"label_comp_id", compID}, // TODO: change to correct comp_id getCategory("pdbx_unobs_or_zero_occ_residues")->emplace({
{"label_seq_id", seqNr > 0 ? std::to_string(seqNr) : ""}}); {"id", std::to_string(++idRes)},
{"polymer_flag", isPolymer ? "Y" : "N"},
{"occupancy_flag", 1},
{"PDB_model_num", unobs.modelNr ? unobs.modelNr : 1},
{"auth_asym_id", std::string{unobs.chain}},
{"auth_comp_id", unobs.res},
{"auth_seq_id", unobs.seq},
{"PDB_ins_code", unobs.iCode == ' ' ? "" : std::string{unobs.iCode}},
{"label_asym_id", asymID},
{"label_comp_id", compID}, // TODO: change to correct comp_id
{"label_seq_id", seqNr > 0 ? std::to_string(seqNr) : ""}
});
} }
else else
{ {
for (auto &atom : unobs.atoms) for (auto &atom : unobs.atoms)
{ {
getCategory("pdbx_unobs_or_zero_occ_atoms")->emplace({{"id", std::to_string(++idAtom)}, {"polymer_flag", isPolymer ? "Y" : "N"}, {"occupancy_flag", 1}, {"PDB_model_num", unobs.modelNr ? unobs.modelNr : 1}, {"auth_asym_id", std::string{unobs.chain}}, {"auth_comp_id", unobs.res}, {"auth_seq_id", unobs.seq}, {"PDB_ins_code", unobs.iCode == ' ' ? "" : std::string{unobs.iCode}}, {"auth_atom_id", atom}, {"label_asym_id", asymID}, {"label_comp_id", compID}, // TODO: change to correct comp_id getCategory("pdbx_unobs_or_zero_occ_atoms")->emplace({
{"label_seq_id", seqNr > 0 ? std::to_string(seqNr) : ""}, {"id", std::to_string(++idAtom)},
{"label_atom_id", atom}}); {"polymer_flag", isPolymer ? "Y" : "N"},
{"occupancy_flag", 1},
{"PDB_model_num", unobs.modelNr ? unobs.modelNr : 1},
{"auth_asym_id", std::string{unobs.chain}},
{"auth_comp_id", unobs.res},
{"auth_seq_id", unobs.seq},
{"PDB_ins_code", unobs.iCode == ' ' ? "" : std::string{unobs.iCode}},
{"auth_atom_id", atom},
{"label_asym_id", asymID},
{"label_comp_id", compID}, // TODO: change to correct comp_id
{"label_seq_id", seqNr > 0 ? std::to_string(seqNr) : ""},
{"label_atom_id", atom}
});
} }
} }
} }
...@@ -4288,14 +4538,18 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr) ...@@ -4288,14 +4538,18 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr)
{"src_method", "man"}, {"src_method", "man"},
{"pdbx_description", branchName}}); {"pdbx_description", branchName}});
getCategory("pdbx_entity_branch")->emplace({{"entity_id", entityID}, {"type", "oligosaccharide"}}); getCategory("pdbx_entity_branch")->emplace({{"entity_id", entityID},
{"type", "oligosaccharide"}});
int num = 0; int num = 0;
std::map<ATOM_REF, int> branch_list; std::map<ATOM_REF, int> branch_list;
for (auto &s : sugarTree) for (auto &s : sugarTree)
{ {
getCategory("pdbx_entity_branch_list")->emplace({{"entity_id", entityID}, {"comp_id", s.c1.resName}, {"num", ++num}, {"hetero", ci.size() == 1 ? "n" : "y"}}); getCategory("pdbx_entity_branch_list")->emplace({{"entity_id", entityID},
{"comp_id", s.c1.resName},
{"num", ++num},
{"hetero", ci.size() == 1 ? "n" : "y"}});
branch_list[s.c1] = num; branch_list[s.c1] = num;
} }
...@@ -4327,7 +4581,10 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr) ...@@ -4327,7 +4581,10 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr)
std::string asymID = cif::cifIdForNumber(asymNr++); std::string asymID = cif::cifIdForNumber(asymNr++);
getCategory("struct_asym")->emplace({{"id", asymID}, {"pdbx_blank_PDB_chainid_flag", si->chainID == ' ' ? "Y" : "N"}, {"pdbx_modified", "N"}, {"entity_id", entityID}}); getCategory("struct_asym")->emplace({{"id", asymID},
{"pdbx_blank_PDB_chainid_flag", si->chainID == ' ' ? "Y" : "N"},
{"pdbx_modified", "N"},
{"entity_id", entityID}});
std::string iCode{si->iCode}; std::string iCode{si->iCode};
ba::trim(iCode); ba::trim(iCode);
...@@ -4337,7 +4594,19 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr) ...@@ -4337,7 +4594,19 @@ void PDBFileParser::ConstructSugarTrees(int &asymNr)
int num = 0; int num = 0;
for (auto s : sugarTree) for (auto s : sugarTree)
{ {
getCategory("pdbx_branch_scheme")->emplace({{"asym_id", asymID}, {"entity_id", entityID}, {"mon_id", s.c1.resName}, {"num", ++num}, {"pdb_asym_id", asymID}, {"pdb_mon_id", s.c1.resName}, {"pdb_seq_num", num}, {"auth_asym_id", std::string{s.c1.chainID}}, {"auth_mon_id", s.next.resName}, {"auth_seq_num", s.c1.resSeq}, {"hetero", ci.size() == 1 ? "n" : "y"}}); getCategory("pdbx_branch_scheme")->emplace({
{"asym_id", asymID},
{"entity_id", entityID},
{"mon_id", s.c1.resName},
{"num", ++num},
{"pdb_asym_id", asymID},
{"pdb_mon_id", s.c1.resName},
{"pdb_seq_num", num},
{"auth_asym_id", std::string{s.c1.chainID}},
{"auth_mon_id", s.next.resName},
{"auth_seq_num", s.c1.resSeq},
{"hetero", ci.size() == 1 ? "n" : "y"}
});
auto k = std::make_tuple(s.c1.chainID, s.c1.resSeq, s.c1.iCode); auto k = std::make_tuple(s.c1.chainID, s.c1.resSeq, s.c1.iCode);
assert(mChainSeq2AsymSeq.count(k) == 0); assert(mChainSeq2AsymSeq.count(k) == 0);
...@@ -4506,7 +4775,10 @@ void PDBFileParser::ParseSecondaryStructure() ...@@ -4506,7 +4775,10 @@ void PDBFileParser::ParseSecondaryStructure()
if (sense != 0) if (sense != 0)
{ {
getCategory("struct_sheet_order")->emplace({{"sheet_id", sheetID}, {"range_id_1", rangeID}, {"range_id_2", rangeID + 1}, {"sense", sense == -1 ? "anti-parallel" : "parallel"}}); getCategory("struct_sheet_order")->emplace({{"sheet_id", sheetID},
{"range_id_1", rangeID},
{"range_id_2", rangeID + 1},
{"sense", sense == -1 ? "anti-parallel" : "parallel"}});
} }
std::string begAsymID, endAsymID; std::string begAsymID, endAsymID;
...@@ -4559,17 +4831,30 @@ void PDBFileParser::ParseSecondaryStructure() ...@@ -4559,17 +4831,30 @@ void PDBFileParser::ParseSecondaryStructure()
std::cerr << "skipping unmatched pdbx_struct_sheet_hbond record" << std::endl; std::cerr << "skipping unmatched pdbx_struct_sheet_hbond record" << std::endl;
} }
else else
getCategory("pdbx_struct_sheet_hbond")->emplace({{"sheet_id", sheetID}, {"range_id_1", rangeID}, {"range_id_2", rangeID + 1}, {"range_1_label_atom_id", vS(57, 60)}, {"range_1_label_comp_id", vS(61, 63)}, {"range_1_label_asym_id", r1AsymID}, {"range_1_label_seq_id", r1Seq}, {"range_1_PDB_ins_code", vS(70, 70)}, {"range_1_auth_atom_id", vS(57, 60)}, {"range_1_auth_comp_id", vS(61, 63)}, {"range_1_auth_asym_id", vS(65, 65)}, {"range_1_auth_seq_id", vI(66, 69)}, getCategory("pdbx_struct_sheet_hbond")->emplace({
{"sheet_id", sheetID},
{"range_2_label_atom_id", vS(42, 45)}, {"range_id_1", rangeID},
{"range_2_label_comp_id", vS(46, 48)}, {"range_id_2", rangeID + 1},
{"range_2_label_asym_id", r2AsymID}, {"range_1_label_atom_id", vS(57, 60)},
{"range_2_label_seq_id", r2Seq}, {"range_1_label_comp_id", vS(61, 63)},
{"range_2_PDB_ins_code", vS(55, 55)}, {"range_1_label_asym_id", r1AsymID},
{"range_2_auth_atom_id", vS(42, 45)}, {"range_1_label_seq_id", r1Seq},
{"range_2_auth_comp_id", vS(46, 48)}, {"range_1_PDB_ins_code", vS(70, 70)},
{"range_2_auth_asym_id", vS(50, 50)}, {"range_1_auth_atom_id", vS(57, 60)},
{"range_2_auth_seq_id", vI(51, 54)}}); {"range_1_auth_comp_id", vS(61, 63)},
{"range_1_auth_asym_id", vS(65, 65)},
{"range_1_auth_seq_id", vI(66, 69)},
{"range_2_label_atom_id", vS(42, 45)},
{"range_2_label_comp_id", vS(46, 48)},
{"range_2_label_asym_id", r2AsymID},
{"range_2_label_seq_id", r2Seq},
{"range_2_PDB_ins_code", vS(55, 55)},
{"range_2_auth_atom_id", vS(42, 45)},
{"range_2_auth_comp_id", vS(46, 48)},
{"range_2_auth_asym_id", vS(50, 50)},
{"range_2_auth_seq_id", vI(51, 54)}
});
} }
if (sense != 0) if (sense != 0)
...@@ -4798,7 +5083,8 @@ void PDBFileParser::ParseConnectivtyAnnotation() ...@@ -4798,7 +5083,8 @@ void PDBFileParser::ParseConnectivtyAnnotation()
continue; continue;
} }
getCategory("struct_conn")->emplace({{"id", type + std::to_string(linkNr)}, {"conn_type_id", type}, getCategory("struct_conn")->emplace({{"id", type + std::to_string(linkNr)},
{"conn_type_id", type},
// { "ccp4_link_id", ccp4LinkID }, // { "ccp4_link_id", ccp4LinkID },
...@@ -4871,7 +5157,24 @@ void PDBFileParser::ParseConnectivtyAnnotation() ...@@ -4871,7 +5157,24 @@ void PDBFileParser::ParseConnectivtyAnnotation()
std::string iCode1str = iCode1 == ' ' ? std::string() : std::string{iCode1}; std::string iCode1str = iCode1 == ' ' ? std::string() : std::string{iCode1};
std::string iCode2str = iCode2 == ' ' ? std::string() : std::string{iCode2}; std::string iCode2str = iCode2 == ' ' ? std::string() : std::string{iCode2};
getCategory("struct_mon_prot_cis")->emplace({{"pdbx_id", serNum}, {"label_comp_id", pep1}, {"label_seq_id", lResSeq1}, {"label_asym_id", lAsym1}, {"label_alt_id", "."}, {"pdbx_PDB_ins_code", iCode1str}, {"auth_comp_id", pep1}, {"auth_seq_id", seqNum1}, {"auth_asym_id", std::string{chainID1}}, {"pdbx_label_comp_id_2", pep2}, {"pdbx_label_seq_id_2", lResSeq2}, {"pdbx_label_asym_id_2", lAsym2}, {"pdbx_PDB_ins_code_2", iCode2str}, {"pdbx_auth_comp_id_2", pep2}, {"pdbx_auth_seq_id_2", seqNum2}, {"pdbx_auth_asym_id_2", std::string{chainID2}}, {"pdbx_PDB_model_num", modNum}, {"pdbx_omega_angle", measure}}); getCategory("struct_mon_prot_cis")->emplace({{"pdbx_id", serNum},
{"label_comp_id", pep1},
{"label_seq_id", lResSeq1},
{"label_asym_id", lAsym1},
{"label_alt_id", "."},
{"pdbx_PDB_ins_code", iCode1str},
{"auth_comp_id", pep1},
{"auth_seq_id", seqNum1},
{"auth_asym_id", std::string{chainID1}},
{"pdbx_label_comp_id_2", pep2},
{"pdbx_label_seq_id_2", lResSeq2},
{"pdbx_label_asym_id_2", lAsym2},
{"pdbx_PDB_ins_code_2", iCode2str},
{"pdbx_auth_comp_id_2", pep2},
{"pdbx_auth_seq_id_2", seqNum2},
{"pdbx_auth_asym_id_2", std::string{chainID2}},
{"pdbx_PDB_model_num", modNum},
{"pdbx_omega_angle", measure}});
continue; continue;
} }
...@@ -4964,7 +5267,9 @@ void PDBFileParser::ParseCrystallographic() ...@@ -4964,7 +5267,9 @@ void PDBFileParser::ParseCrystallographic()
{ {
} }
getCategory("symmetry")->emplace({{"entry_id", mStructureID}, {"space_group_name_H-M", spaceGroup}, {"Int_Tables_number", intTablesNr}}); getCategory("symmetry")->emplace({{"entry_id", mStructureID},
{"space_group_name_H-M", spaceGroup},
{"Int_Tables_number", intTablesNr}});
GetNextRecord(); GetNextRecord();
} }
...@@ -5056,7 +5361,20 @@ void PDBFileParser::ParseCoordinateTransformation() ...@@ -5056,7 +5361,20 @@ void PDBFileParser::ParseCoordinateTransformation()
GetNextRecord(); // transformations of the molecule are GetNextRecord(); // transformations of the molecule are
} // contained in the datablock. Otherwise, blank. } // contained in the datablock. Otherwise, blank.
getCategory("struct_ncs_oper")->emplace({{"id", serial}, {"matrix[1][1]", m[0][0]}, {"matrix[1][2]", m[0][1]}, {"matrix[1][3]", m[0][2]}, {"matrix[2][1]", m[1][0]}, {"matrix[2][2]", m[1][1]}, {"matrix[2][3]", m[1][2]}, {"matrix[3][1]", m[2][0]}, {"matrix[3][2]", m[2][1]}, {"matrix[3][3]", m[2][2]}, {"vector[1]", v[0]}, {"vector[2]", v[1]}, {"vector[3]", v[2]}, {"code", igiven ? "given" : ""}}); getCategory("struct_ncs_oper")->emplace({{"id", serial},
{"matrix[1][1]", m[0][0]},
{"matrix[1][2]", m[0][1]},
{"matrix[1][3]", m[0][2]},
{"matrix[2][1]", m[1][0]},
{"matrix[2][2]", m[1][1]},
{"matrix[2][3]", m[1][2]},
{"matrix[3][1]", m[2][0]},
{"matrix[3][2]", m[2][1]},
{"matrix[3][3]", m[2][2]},
{"vector[1]", v[0]},
{"vector[2]", v[1]},
{"vector[3]", v[2]},
{"code", igiven ? "given" : ""}});
} }
} }
...@@ -5215,7 +5533,27 @@ void PDBFileParser::ParseCoordinate(int modelNr) ...@@ -5215,7 +5533,27 @@ void PDBFileParser::ParseCoordinate(int modelNr)
} }
} }
getCategory("atom_site")->emplace({{"group_PDB", groupPDB}, {"id", mAtomID}, {"type_symbol", element}, {"label_atom_id", name}, {"label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."}, {"label_comp_id", resName}, {"label_asym_id", asymID}, {"label_entity_id", entityID}, {"label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."}, {"pdbx_PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}}, {"Cartn_x", x}, {"Cartn_y", y}, {"Cartn_z", z}, {"occupancy", occupancy}, {"B_iso_or_equiv", tempFactor}, {"pdbx_formal_charge", charge}, {"auth_seq_id", resSeq}, {"auth_comp_id", resName}, {"auth_asym_id", std::string{chainID}}, {"auth_atom_id", name}, {"pdbx_PDB_model_num", modelNr}}); getCategory("atom_site")->emplace({{"group_PDB", groupPDB},
{"id", mAtomID},
{"type_symbol", element},
{"label_atom_id", name},
{"label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."},
{"label_comp_id", resName},
{"label_asym_id", asymID},
{"label_entity_id", entityID},
{"label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."},
{"pdbx_PDB_ins_code", iCode == ' ' ? "" : std::string{iCode}},
{"Cartn_x", x},
{"Cartn_y", y},
{"Cartn_z", z},
{"occupancy", occupancy},
{"B_iso_or_equiv", tempFactor},
{"pdbx_formal_charge", charge},
{"auth_seq_id", resSeq},
{"auth_comp_id", resName},
{"auth_asym_id", std::string{chainID}},
{"auth_atom_id", name},
{"pdbx_PDB_model_num", modelNr}});
InsertAtomType(element); InsertAtomType(element);
...@@ -5237,7 +5575,23 @@ void PDBFileParser::ParseCoordinate(int modelNr) ...@@ -5237,7 +5575,23 @@ void PDBFileParser::ParseCoordinate(int modelNr)
auto f = [](float f) -> std::string auto f = [](float f) -> std::string
{ return (boost::format("%6.4f") % f).str(); }; { return (boost::format("%6.4f") % f).str(); };
getCategory("atom_site_anisotrop")->emplace({{"id", mAtomID}, {"type_symbol", element}, {"pdbx_label_atom_id", name}, {"pdbx_label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."}, {"pdbx_label_comp_id", resName}, {"pdbx_label_asym_id", asymID}, {"pdbx_label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."}, {"U[1][1]", f(u11 / 10000.f)}, {"U[2][2]", f(u22 / 10000.f)}, {"U[3][3]", f(u33 / 10000.f)}, {"U[1][2]", f(u12 / 10000.f)}, {"U[1][3]", f(u13 / 10000.f)}, {"U[2][3]", f(u23 / 10000.f)}, {"pdbx_auth_seq_id", resSeq}, {"pdbx_auth_comp_id", resName}, {"pdbx_auth_asym_id", std::string{chainID}}, {"pdbx_auth_atom_id", name}}); getCategory("atom_site_anisotrop")->emplace({{"id", mAtomID},
{"type_symbol", element},
{"pdbx_label_atom_id", name},
{"pdbx_label_alt_id", altLoc != ' ' ? std::string{altLoc} : "."},
{"pdbx_label_comp_id", resName},
{"pdbx_label_asym_id", asymID},
{"pdbx_label_seq_id", (isResseq and seqID > 0) ? std::to_string(seqID) : "."},
{"U[1][1]", f(u11 / 10000.f)},
{"U[2][2]", f(u22 / 10000.f)},
{"U[3][3]", f(u33 / 10000.f)},
{"U[1][2]", f(u12 / 10000.f)},
{"U[1][3]", f(u13 / 10000.f)},
{"U[2][3]", f(u23 / 10000.f)},
{"pdbx_auth_seq_id", resSeq},
{"pdbx_auth_comp_id", resName},
{"pdbx_auth_asym_id", std::string{chainID}},
{"pdbx_auth_atom_id", name}});
} }
} }
......
...@@ -28,12 +28,249 @@ ...@@ -28,12 +28,249 @@
#include <valarray> #include <valarray>
#include "cif++/Point.hpp" #include "cif++/Point.hpp"
#include "cif++/Matrix.hpp"
namespace mmcif namespace mmcif
{ {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// We're using expression templates here
template <typename M>
class MatrixExpression
{
public:
uint32_t dim_m() const { return static_cast<const M&>(*this).dim_m(); }
uint32_t dim_n() const { return static_cast<const M&>(*this).dim_n(); }
double &operator()(uint32_t i, uint32_t j)
{
return static_cast<M&>(*this).operator()(i, j);
}
double operator()(uint32_t i, uint32_t j) const
{
return static_cast<const M&>(*this).operator()(i, j);
}
};
// --------------------------------------------------------------------
// matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
// element m i,j is mapped to [i * n + j] and thus storage is row major
class Matrix : public MatrixExpression<Matrix>
{
public:
template <typename M2>
Matrix(const MatrixExpression<M2> &m)
: m_m(m.dim_m())
, m_n(m.dim_n())
, m_data(m_m * m_n)
{
for (uint32_t i = 0; i < m_m; ++i)
{
for (uint32_t j = 0; j < m_n; ++j)
operator()(i, j) = m(i, j);
}
}
Matrix(size_t m, size_t n, double v = 0)
: m_m(m)
, m_n(n)
, m_data(m_m * m_n)
{
std::fill(m_data.begin(), m_data.end(), v);
}
Matrix() = default;
Matrix(Matrix &&m) = default;
Matrix(const Matrix &m) = default;
Matrix &operator=(Matrix &&m) = default;
Matrix &operator=(const Matrix &m) = default;
uint32_t dim_m() const { return m_m; }
uint32_t dim_n() const { return m_n; }
double operator()(uint32_t i, uint32_t j) const
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
double &operator()(uint32_t i, uint32_t j)
{
assert(i < m_m);
assert(j < m_n);
return m_data[i * m_n + j];
}
private:
uint32_t m_m = 0, m_n = 0;
std::vector<double> m_data;
};
// --------------------------------------------------------------------
class SymmetricMatrix : public MatrixExpression<SymmetricMatrix>
{
public:
SymmetricMatrix(uint32_t n, double v = 0)
: m_n(n)
, m_data((m_n * (m_n + 1)) / 2)
{
std::fill(m_data.begin(), m_data.end(), v);
}
SymmetricMatrix() = default;
SymmetricMatrix(SymmetricMatrix &&m) = default;
SymmetricMatrix(const SymmetricMatrix &m) = default;
SymmetricMatrix &operator=(SymmetricMatrix &&m) = default;
SymmetricMatrix &operator=(const SymmetricMatrix &m) = default;
uint32_t dim_m() const { return m_n; }
uint32_t dim_n() const { return m_n; }
double operator()(uint32_t i, uint32_t j) const
{
return i < j
? m_data[(j * (j + 1)) / 2 + i]
: m_data[(i * (i + 1)) / 2 + j];
}
double &operator()(uint32_t i, uint32_t j)
{
if (i > j)
std::swap(i, j);
assert(j < m_n);
return m_data[(j * (j + 1)) / 2 + i];
}
private:
uint32_t m_n;
std::vector<double> m_data;
};
class IdentityMatrix : public MatrixExpression<IdentityMatrix>
{
public:
IdentityMatrix(uint32_t n)
: m_n(n)
{
}
uint32_t dim_m() const { return m_n; }
uint32_t dim_n() const { return m_n; }
double operator()(uint32_t i, uint32_t j) const
{
return i == j ? 1 : 0;
}
private:
uint32_t m_n;
};
// --------------------------------------------------------------------
// matrix functions, implemented as expression templates
template<typename M1, typename M2>
class MatrixSubtraction : public MatrixExpression<MatrixSubtraction<M1, M2>>
{
public:
MatrixSubtraction(const M1 &m1, const M2 &m2)
: m_m1(m1), m_m2(m2)
{
assert(m_m1.dim_m() == m_m2.dim_m());
assert(m_m1.dim_n() == m_m2.dim_n());
}
uint32_t dim_m() const { return m_m1.dim_m(); }
uint32_t dim_n() const { return m_m1.dim_n(); }
double operator()(uint32_t i, uint32_t j) const
{
return m_m1(i, j) - m_m2(i, j);
}
private:
const M1 &m_m1;
const M2 &m_m2;
};
template<typename M1, typename M2>
MatrixSubtraction<M1, M2> operator-(const MatrixExpression<M1> &m1, const MatrixExpression<M2> &m2)
{
return MatrixSubtraction(*static_cast<const M1*>(&m1), *static_cast<const M2*>(&m2));
}
template<typename M>
class MatrixMultiplication : public MatrixExpression<MatrixMultiplication<M>>
{
public:
MatrixMultiplication(const M &m, double v)
: m_m(m), m_v(v)
{
}
uint32_t dim_m() const { return m_m.dim_m(); }
uint32_t dim_n() const { return m_m.dim_n(); }
double operator()(uint32_t i, uint32_t j) const
{
return m_m(i, j) * m_v;
}
private:
const M &m_m;
double m_v;
};
template<typename M>
MatrixMultiplication<M> operator*(const MatrixExpression<M> &m, double v)
{
return MatrixMultiplication(*static_cast<const M*>(&m), v);
}
// --------------------------------------------------------------------
template<class M1>
Matrix Cofactors(const M1& m)
{
Matrix cf(m.dim_m(), m.dim_m());
const size_t ixs[4][3] =
{
{ 1, 2, 3 },
{ 0, 2, 3 },
{ 0, 1, 3 },
{ 0, 1, 2 }
};
for (size_t x = 0; x < 4; ++x)
{
const size_t* ix = ixs[x];
for (size_t y = 0; y < 4; ++y)
{
const size_t* iy = ixs[y];
cf(x, y) =
m(ix[0], iy[0]) * m(ix[1], iy[1]) * m(ix[2], iy[2]) +
m(ix[0], iy[1]) * m(ix[1], iy[2]) * m(ix[2], iy[0]) +
m(ix[0], iy[2]) * m(ix[1], iy[0]) * m(ix[2], iy[1]) -
m(ix[0], iy[2]) * m(ix[1], iy[1]) * m(ix[2], iy[0]) -
m(ix[0], iy[1]) * m(ix[1], iy[0]) * m(ix[2], iy[2]) -
m(ix[0], iy[0]) * m(ix[1], iy[2]) * m(ix[2], iy[1]);
if ((x + y) % 2 == 1)
cf(x, y) *= -1;
}
}
return cf;
}
// --------------------------------------------------------------------
Quaternion Normalize(Quaternion q) Quaternion Normalize(Quaternion q)
{ {
...@@ -102,14 +339,14 @@ Point CenterPoints(std::vector<Point>& Points) ...@@ -102,14 +339,14 @@ Point CenterPoints(std::vector<Point>& Points)
return t; return t;
} }
Point Centroid(std::vector<Point>& Points) Point Centroid(const std::vector<Point>& pts)
{ {
Point result; Point result;
for (Point& pt : Points) for (auto &pt : pts)
result += pt; result += pt;
result /= static_cast<float>(Points.size()); result /= static_cast<float>(pts.size());
return result; return result;
} }
...@@ -175,7 +412,7 @@ double LargestDepressedQuarticSolution(double a, double b, double c) ...@@ -175,7 +412,7 @@ double LargestDepressedQuarticSolution(double a, double b, double c)
Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& pb) Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& pb)
{ {
// First calculate M, a 3x3 Matrix containing the sums of products of the coordinates of A and B // First calculate M, a 3x3 Matrix containing the sums of products of the coordinates of A and B
Matrix<double> M(3, 3, 0); Matrix M(3, 3, 0);
for (uint32_t i = 0; i < pa.size(); ++i) for (uint32_t i = 0; i < pa.size(); ++i)
{ {
...@@ -188,7 +425,7 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p ...@@ -188,7 +425,7 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p
} }
// Now calculate N, a symmetric 4x4 Matrix // Now calculate N, a symmetric 4x4 Matrix
SymmetricMatrix<double> N(4); SymmetricMatrix N(4);
N(0, 0) = M(0, 0) + M(1, 1) + M(2, 2); N(0, 0) = M(0, 0) + M(1, 1) + M(2, 2);
N(0, 1) = M(1, 2) - M(2, 1); N(0, 1) = M(1, 2) - M(2, 1);
...@@ -225,6 +462,7 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p ...@@ -225,6 +462,7 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p
M(1, 2) * M(2, 0) * M(0, 1) + M(1, 2) * M(2, 0) * M(0, 1) +
M(2, 1) * M(1, 0) * M(0, 2)); M(2, 1) * M(1, 0) * M(0, 2));
// E is the determinant of N:
double E = double E =
(N(0,0) * N(1,1) - N(0,1) * N(0,1)) * (N(2,2) * N(3,3) - N(2,3) * N(2,3)) + (N(0,0) * N(1,1) - N(0,1) * N(0,1)) * (N(2,2) * N(3,3) - N(2,3) * N(2,3)) +
(N(0,1) * N(0,2) - N(0,0) * N(2,1)) * (N(2,1) * N(3,3) - N(2,3) * N(1,3)) + (N(0,1) * N(0,2) - N(0,0) * N(2,1)) * (N(2,1) * N(3,3) - N(2,3) * N(1,3)) +
...@@ -234,47 +472,22 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p ...@@ -234,47 +472,22 @@ Quaternion AlignPoints(const std::vector<Point>& pa, const std::vector<Point>& p
(N(0,2) * N(1,3) - N(2,1) * N(0,3)) * (N(0,2) * N(1,3) - N(2,1) * N(0,3)); (N(0,2) * N(1,3) - N(2,1) * N(0,3)) * (N(0,2) * N(1,3) - N(2,1) * N(0,3));
// solve quartic // solve quartic
double lm = LargestDepressedQuarticSolution(C, D, E); double lambda = LargestDepressedQuarticSolution(C, D, E);
// calculate t = (N - λI) // calculate t = (N - λI)
Matrix<double> li = IdentityMatrix<double>(4) * lm; Matrix t = N - IdentityMatrix(4) * lambda;
Matrix<double> t = N - li;
// calculate a Matrix of cofactors for t // calculate a Matrix of cofactors for t
Matrix<double> cf(4, 4); Matrix cf = Cofactors(t);
const uint32_t ixs[4][3] = int maxR = 0;
for (int r = 1; r < 4; ++r)
{ {
{ 1, 2, 3 }, if (std::abs(cf(r, 0)) > std::abs(cf(maxR, 0)))
{ 0, 2, 3 },
{ 0, 1, 3 },
{ 0, 1, 2 }
};
uint32_t maxR = 0;
for (uint32_t r = 0; r < 4; ++r)
{
const uint32_t* ir = ixs[r];
for (uint32_t c = 0; c < 4; ++c)
{
const uint32_t* ic = ixs[c];
cf(r, c) =
t(ir[0], ic[0]) * t(ir[1], ic[1]) * t(ir[2], ic[2]) +
t(ir[0], ic[1]) * t(ir[1], ic[2]) * t(ir[2], ic[0]) +
t(ir[0], ic[2]) * t(ir[1], ic[0]) * t(ir[2], ic[1]) -
t(ir[0], ic[2]) * t(ir[1], ic[1]) * t(ir[2], ic[0]) -
t(ir[0], ic[1]) * t(ir[1], ic[0]) * t(ir[2], ic[2]) -
t(ir[0], ic[0]) * t(ir[1], ic[2]) * t(ir[2], ic[1]);
}
if (r > maxR and cf(r, 0) > cf(maxR, 0))
maxR = r; maxR = r;
} }
// NOTE the negation of the y here, why? Maybe I swapped r/c above? Quaternion q(cf(maxR, 0), cf(maxR, 1), cf(maxR, 2), cf(maxR, 3));
Quaternion q(cf(maxR, 0), cf(maxR, 1), -cf(maxR, 2), cf(maxR, 3));
q = Normalize(q); q = Normalize(q);
return q; return q;
......
...@@ -897,7 +897,6 @@ void CalculateBetaSheets(std::vector<Res>& inResidues, DSSP_Statistics& stats) ...@@ -897,7 +897,6 @@ void CalculateBetaSheets(std::vector<Res>& inResidues, DSSP_Statistics& stats)
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// TODO: improve alpha helix calculation by better recognizing pi-helices
void CalculateAlphaHelices(std::vector<Res>& inResidues, DSSP_Statistics& stats, bool inPreferPiHelices = true) void CalculateAlphaHelices(std::vector<Res>& inResidues, DSSP_Statistics& stats, bool inPreferPiHelices = true)
{ {
......
...@@ -216,9 +216,9 @@ struct AtomImpl ...@@ -216,9 +216,9 @@ struct AtomImpl
, mLocation(i.mLocation) , mLocation(i.mLocation)
, mRefcount(1) , mRefcount(1)
, mRow(i.mRow) , mRow(i.mRow)
, mCachedRefs(i.mCachedRefs)
, mCompound(i.mCompound) , mCompound(i.mCompound)
, mRadius(i.mRadius) , mRadius(i.mRadius)
, mCachedProperties(i.mCachedProperties)
, mSymmetryCopy(i.mSymmetryCopy) , mSymmetryCopy(i.mSymmetryCopy)
, mClone(true) , mClone(true)
// , mRTop(i.mRTop), mD(i.mD) // , mRTop(i.mRTop), mD(i.mD)
...@@ -270,9 +270,9 @@ struct AtomImpl ...@@ -270,9 +270,9 @@ struct AtomImpl
, mLocation(loc) , mLocation(loc)
, mRefcount(1) , mRefcount(1)
, mRow(impl.mRow) , mRow(impl.mRow)
, mCachedRefs(impl.mCachedRefs)
, mCompound(impl.mCompound) , mCompound(impl.mCompound)
, mRadius(impl.mRadius) , mRadius(impl.mRadius)
, mCachedProperties(impl.mCachedProperties)
, mSymmetryCopy(true) , mSymmetryCopy(true)
, mSymmetryOperator(sym_op) , mSymmetryOperator(sym_op)
{ {
...@@ -317,13 +317,15 @@ struct AtomImpl ...@@ -317,13 +317,15 @@ struct AtomImpl
auto cat = mDb.get("atom_site_anisotrop"); auto cat = mDb.get("atom_site_anisotrop");
if (cat) if (cat)
{ {
auto r = cat->find1(cif::Key("id") == mID); try
if (not r.empty())
{ {
result = true; auto r = cat->find1(cif::Key("id") == mID);
cif::tie(anisou[0], anisou[1], anisou[2], anisou[3], anisou[4], anisou[5]) = cif::tie(anisou[0], anisou[1], anisou[2], anisou[3], anisou[4], anisou[5]) =
r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]"); r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]");
result = true;
}
catch(const std::exception& e)
{
} }
} }
...@@ -338,9 +340,9 @@ struct AtomImpl ...@@ -338,9 +340,9 @@ struct AtomImpl
if (not mClone) if (not mClone)
{ {
mRow["Cartn_x"] = p.getX(); property("Cartn_x", std::to_string(p.getX()));
mRow["Cartn_y"] = p.getY(); property("Cartn_y", std::to_string(p.getY()));
mRow["Cartn_z"] = p.getZ(); property("Cartn_z", std::to_string(p.getZ()));
} }
// boost::format kPosFmt("%.3f"); // boost::format kPosFmt("%.3f");
...@@ -382,26 +384,31 @@ struct AtomImpl ...@@ -382,26 +384,31 @@ struct AtomImpl
return mRadius; return mRadius;
} }
const std::string &property(const std::string &name) const const std::string property(const std::string_view name) const
{ {
static std::string kEmptyString; for (auto &&[tag, ref] : mCachedRefs)
auto i = mCachedProperties.find(name);
if (i == mCachedProperties.end())
{ {
auto v = mRow[name]; if (tag == name)
if (v.empty()) return ref.as<std::string>();
return kEmptyString;
return mCachedProperties[name] = v.as<std::string>();
} }
else
return i->second; mCachedRefs.emplace_back(name, mRow[name]);
return std::get<1>(mCachedRefs.back()).as<std::string>();
} }
void property(const std::string &name, const std::string &value) void property(const std::string_view name, const std::string &value)
{ {
mRow[name] = value; for (auto &&[tag, ref] : mCachedRefs)
{
if (tag != name)
continue;
ref = value;
return;
}
mCachedRefs.emplace_back(name, mRow[name]);
std::get<1>(mCachedRefs.back()) = value;
} }
int compare(const AtomImpl &b) const int compare(const AtomImpl &b) const
...@@ -432,9 +439,11 @@ struct AtomImpl ...@@ -432,9 +439,11 @@ struct AtomImpl
Point mLocation; Point mLocation;
int mRefcount; int mRefcount;
cif::Row mRow; cif::Row mRow;
mutable std::vector<std::tuple<std::string,cif::detail::ItemReference>> mCachedRefs;
mutable const Compound *mCompound = nullptr; mutable const Compound *mCompound = nullptr;
float mRadius = std::nanf("4"); float mRadius = std::nanf("4");
mutable std::map<std::string, std::string> mCachedProperties;
bool mSymmetryCopy = false; bool mSymmetryCopy = false;
bool mClone = false; bool mClone = false;
...@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const ...@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const
} }
template <> template <>
std::string Atom::property<std::string>(const std::string &name) const std::string Atom::property<std::string>(const std::string_view name) const
{ {
return impl()->property(name); return impl()->property(name);
} }
template <> template <>
int Atom::property<int>(const std::string &name) const int Atom::property<int>(const std::string_view name) const
{ {
auto v = impl()->property(name); auto v = impl()->property(name);
return v.empty() ? 0 : stoi(v); return v.empty() ? 0 : stoi(v);
} }
template <> template <>
float Atom::property<float>(const std::string &name) const float Atom::property<float>(const std::string_view name) const
{ {
return stof(impl()->property(name)); return stof(impl()->property(name));
} }
void Atom::property(const std::string &name, const std::string &value) void Atom::property(const std::string_view name, const std::string &value)
{ {
impl()->property(name, value); impl()->property(name, value);
} }
...@@ -1736,7 +1745,7 @@ File::~File() ...@@ -1736,7 +1745,7 @@ File::~File()
delete mImpl; delete mImpl;
} }
cif::Datablock& File::createDatablock(const std::string &name) cif::Datablock& File::createDatablock(const std::string_view name)
{ {
auto db = new cif::Datablock(name); auto db = new cif::Datablock(name);
...@@ -1978,6 +1987,58 @@ Atom Structure::getAtomByLabel(const std::string &atomID, const std::string &asy ...@@ -1978,6 +1987,58 @@ Atom Structure::getAtomByLabel(const std::string &atomID, const std::string &asy
throw std::out_of_range("Could not find atom with specified label"); throw std::out_of_range("Could not find atom with specified label");
} }
Atom Structure::getAtomByPosition(Point p) const
{
double distance = std::numeric_limits<double>::max();
size_t index = std::numeric_limits<size_t>::max();
for (size_t i = 0; i < mAtoms.size(); ++i)
{
auto &a = mAtoms.at(i);
auto d = Distance(a.location(), p);
if (d < distance)
{
distance = d;
index = i;
}
}
if (index < mAtoms.size())
return mAtoms.at(index);
return {};
}
Atom Structure::getAtomByPositionAndType(Point p, std::string_view type, std::string_view res_type) const
{
double distance = std::numeric_limits<double>::max();
size_t index = std::numeric_limits<size_t>::max();
for (size_t i = 0; i < mAtoms.size(); ++i)
{
auto &a = mAtoms.at(i);
if (a.labelCompID() != res_type)
continue;
if (a.labelAtomID() != type)
continue;
auto d = Distance(a.location(), p);
if (d < distance)
{
distance = d;
index = i;
}
}
if (index < mAtoms.size())
return mAtoms.at(index);
return {};
}
const Residue &Structure::getResidue(const std::string &asymID, const std::string &compID, int seqID) const const Residue &Structure::getResidue(const std::string &asymID, const std::string &compID, int seqID) const
{ {
for (auto &poly : mPolymers) for (auto &poly : mPolymers)
...@@ -2014,12 +2075,35 @@ const Residue &Structure::getResidue(const std::string &asymID, const std::strin ...@@ -2014,12 +2075,35 @@ const Residue &Structure::getResidue(const std::string &asymID, const std::strin
throw std::out_of_range("Could not find residue " + asymID + '/' + std::to_string(seqID)); throw std::out_of_range("Could not find residue " + asymID + '/' + std::to_string(seqID));
} }
Residue &Structure::getResidue(const std::string &asymID, const std::string &compID, int seqID)
{
return const_cast<Residue&>(const_cast<Structure const&>(*this).getResidue(asymID, compID, seqID));
}
const Residue &Structure::getResidue(const std::string &asymID) const
{
for (auto &res : mNonPolymers)
{
if (res.asymID() != asymID)
continue;
return res;
}
throw std::out_of_range("Could not find residue " + asymID);
}
Residue &Structure::getResidue(const std::string &asymID)
{
return const_cast<Residue&>(const_cast<Structure const&>(*this).getResidue(asymID));
}
File &Structure::getFile() const File &Structure::getFile() const
{ {
return mFile; return mFile;
} }
cif::Category &Structure::category(const char *name) const cif::Category &Structure::category(std::string_view name) const
{ {
auto &db = datablock(); auto &db = datablock();
return db[name]; return db[name];
...@@ -2352,7 +2436,7 @@ void Structure::moveAtom(Atom &a, Point p) ...@@ -2352,7 +2436,7 @@ void Structure::moveAtom(Atom &a, Point p)
a.location(p); a.location(p);
} }
void Structure::changeResidue(const Residue &res, const std::string &newCompound, void Structure::changeResidue(Residue &res, const std::string &newCompound,
const std::vector<std::tuple<std::string, std::string>> &remappedAtoms) const std::vector<std::tuple<std::string, std::string>> &remappedAtoms)
{ {
using namespace cif::literals; using namespace cif::literals;
...@@ -2416,6 +2500,8 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound ...@@ -2416,6 +2500,8 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
else else
insertCompound(newCompound, false); insertCompound(newCompound, false);
res.setCompoundID(newCompound);
auto &atomSites = db["atom_site"]; auto &atomSites = db["atom_site"];
auto atoms = res.atoms(); auto atoms = res.atoms();
...@@ -2437,8 +2523,15 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound ...@@ -2437,8 +2523,15 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
if (r.size() != 1) if (r.size() != 1)
continue; continue;
if (a1 != a2) if (a2.empty() or a2 == ".")
r.front()["label_atom_id"] = a2; removeAtom(*i);
else if (a1 != a2)
{
auto ra = r.front();
ra["label_atom_id"] = a2;
ra["auth_atom_id"] = a2;
ra["type_symbol"] = AtomTypeTraits(compound->getAtomByID(a2).typeSymbol).symbol();
}
} }
for (auto a : atoms) for (auto a : atoms)
......
...@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup) ...@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup)
return result; return result;
} }
// --------------------------------------------------------------------
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type)
{
if (spacegroup == "P 21 21 2 A")
spacegroup = "P 21 21 2 (a)";
else if (spacegroup.empty())
throw std::runtime_error("No spacegroup, cannot continue");
int result = 0;
if (type == SpacegroupName::full)
{
const size_t N = kNrOfSpaceGroups;
int32_t L = 0, R = static_cast<int32_t>(N - 1);
while (L <= R)
{
int32_t i = (L + R) / 2;
int d = spacegroup.compare(kSpaceGroups[i].name);
if (d > 0)
L = i + 1;
else if (d < 0)
R = i - 1;
else
{
result = kSpaceGroups[i].nr;
break;
}
}
}
else if (type == SpacegroupName::xHM)
{
for (auto &sg : kSpaceGroups)
{
if (sg.xHM == spacegroup)
{
result = sg.nr;
break;
}
}
}
else
{
for (auto &sg : kSpaceGroups)
{
if (sg.Hall == spacegroup)
{
result = sg.nr;
break;
}
}
}
// not found, see if we can find a match based on xHM name
if (result == 0)
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
return result;
}
} }
...@@ -18,7 +18,6 @@ int main(int argc, char* argv[]) ...@@ -18,7 +18,6 @@ int main(int argc, char* argv[])
desc.add_options() desc.add_options()
("input,i", po::value<std::string>(), "Input file") ("input,i", po::value<std::string>(), "Input file")
("help,h", "Display help message") ("help,h", "Display help message")
("version", "Print version")
("verbose,v", "Verbose output") ("verbose,v", "Verbose output")
("debug,d", po::value<int>(), "Debug level (for even more verbose output)"); ("debug,d", po::value<int>(), "Debug level (for even more verbose output)");
...@@ -29,12 +28,6 @@ int main(int argc, char* argv[]) ...@@ -29,12 +28,6 @@ int main(int argc, char* argv[])
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
po::notify(vm); po::notify(vm);
if (vm.count("version"))
{
std::cout << argv[0] << " version " PACKAGE_VERSION << std::endl;
exit(0);
}
if (vm.count("help") or vm.count("input") == 0) if (vm.count("help") or vm.count("input") == 0)
{ {
std::cerr << desc << std::endl; std::cerr << desc << std::endl;
......
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
// #include "cif++/DistanceMap.hpp" // #include "cif++/DistanceMap.hpp"
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/BondMap.hpp" #include "cif++/BondMap.hpp"
#include "cif++/CifValidator.hpp"
namespace tt = boost::test_tools;
std::filesystem::path gTestDir = std::filesystem::current_path(); // filled in first test std::filesystem::path gTestDir = std::filesystem::current_path(); // filled in first test
...@@ -259,8 +263,10 @@ save__cat_2.desc ...@@ -259,8 +263,10 @@ save__cat_2.desc
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -387,8 +393,10 @@ save__cat_1.c ...@@ -387,8 +393,10 @@ save__cat_1.c
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -535,8 +543,10 @@ save__cat_2.desc ...@@ -535,8 +543,10 @@ save__cat_2.desc
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -741,8 +751,10 @@ save__cat_2.parent_id3 ...@@ -741,8 +751,10 @@ save__cat_2.parent_id3
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -963,8 +975,10 @@ cat_2 3 cat_2:cat_1:3 ...@@ -963,8 +975,10 @@ cat_2 3 cat_2:cat_1:3
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1389,9 +1403,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3 ...@@ -1389,9 +1403,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
} buffer(const_cast<char*>(dict), sizeof(dict) - 1); } buffer(const_cast<char*>(dict), sizeof(dict) - 1);
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1687,4 +1702,58 @@ BOOST_AUTO_TEST_CASE(reading_file_1) ...@@ -1687,4 +1702,58 @@ BOOST_AUTO_TEST_CASE(reading_file_1)
cif::File file; cif::File file;
BOOST_CHECK_THROW(file.load(is), std::runtime_error); BOOST_CHECK_THROW(file.load(is), std::runtime_error);
} }
\ No newline at end of file
// 3d tests
using namespace mmcif;
BOOST_AUTO_TEST_CASE(t1)
{
// std::random_device rnd;
// std::mt19937 gen(rnd());
// std::uniform_real_distribution<float> dis(0, 1);
// Quaternion q{ dis(gen), dis(gen), dis(gen), dis(gen) };
// q = Normalize(q);
// Quaternion q{ 0.1, 0.2, 0.3, 0.4 };
Quaternion q{ 0.5, 0.5, 0.5, 0.5 };
q = Normalize(q);
const auto &&[angle0, axis0] = QuaternionToAngleAxis(q);
std::vector<Point> p1{
{ 16.979, 13.301, 44.555 },
{ 18.150, 13.525, 43.680 },
{ 18.656, 14.966, 43.784 },
{ 17.890, 15.889, 44.078 },
{ 17.678, 13.270, 42.255 },
{ 16.248, 13.734, 42.347 },
{ 15.762, 13.216, 43.724 }
};
auto p2 = p1;
Point c1 = CenterPoints(p1);
for (auto &p : p2)
p.rotate(q);
Point c2 = CenterPoints(p2);
auto q2 = AlignPoints(p1, p2);
const auto &&[angle, axis] = QuaternionToAngleAxis(q2);
BOOST_TEST(std::fmod(360 + angle, 360) == std::fmod(360 - angle0, 360), tt::tolerance(0.01));
for (auto &p : p1)
p.rotate(q2);
float rmsd = RMSd(p1, p2);
BOOST_TEST(rmsd < 1e-5);
// std::cout << "rmsd: " << RMSd(p1, p2) << std::endl;
}
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