Gemmi C++ API
Loading...
Searching...
No Matches
chemcomp_xyz.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// Reading coordinates from chemical component or Refmac monomer library files.
4
5#ifndef GEMMI_CHEMCOMP_XYZ_HPP_
6#define GEMMI_CHEMCOMP_XYZ_HPP_
7
8#include <array>
9#include "cifdoc.hpp" // for Block, etc
10#include "fail.hpp" // for fail
11#include "numb.hpp" // for as_number
12#include "model.hpp" // for Atom, Residue, etc
13
14namespace gemmi {
15
16// Reading chemical component as a coordinate file.
17enum class ChemCompModel {
18 Xyz, // _chem_comp_atom.x, etc
19 Example, // _chem_comp_atom.model_Cartn_x
20 Ideal // _chem_comp_atom.pdbx_model_Cartn_x_ideal
21};
22
24 ChemCompModel kind) {
25 std::array<std::string, 3> xyz_tags;
26 switch (kind) {
28 xyz_tags = {{"x", "y", "z"}};
29 break;
31 xyz_tags = {{"model_Cartn_x", "model_Cartn_y", "model_Cartn_z"}};
32 break;
34 xyz_tags = {{"pdbx_model_Cartn_x_ideal",
35 "pdbx_model_Cartn_y_ideal",
36 "pdbx_model_Cartn_z_ideal"}};
37 break;
38 }
39 Residue res;
40 res.seqid.num = 1;
41 cif::Column col =
42 const_cast<cif::Block&>(block).find_values("_chem_comp_atom.comp_id");
43 if (col && col.length() > 0)
44 res.name = col[0];
45 else
46 res.name = block.name.substr(starts_with(block.name, "comp_") ? 5 : 0);
47 cif::Table table = const_cast<cif::Block&>(block).find("_chem_comp_atom.",
48 {"atom_id", "type_symbol", "?charge",
49 xyz_tags[0], xyz_tags[1], xyz_tags[2]});
50 res.atoms.resize(table.length());
51 int n = 0;
52 for (auto row : table) {
53 Atom& atom = res.atoms[n++];
54 atom.name = row.str(0);
55 atom.element = Element(row.str(1));
56 if (row.has2(2))
57 // Charge is defined as integer, but some cif files in the wild have
58 // trailing '.000', so we read it as floating-point number.
59 atom.charge = (signed char) std::round(cif::as_number(row[2]));
60 atom.pos = Position(cif::as_number(row[3]),
63 }
64 return res;
65}
66
68 ChemCompModel kind) {
69 std::string name;
70 switch (kind) {
71 case ChemCompModel::Xyz: name = "xyz"; break;
72 case ChemCompModel::Example: name = "example_xyz"; break;
73 case ChemCompModel::Ideal: name = "ideal_xyz"; break;
74 }
75 Model model(name);
76 model.chains.emplace_back("");
77 model.chains[0].residues.push_back(
79 return model;
80}
81
82// For CCD input - returns a structure with two single-residue models:
83// example (model_Cartn_x) and ideal (pdbx_model_Cartn_x_ideal).
84// For Refmac dictionary (monomer library) files returns structure with
85// a single model.
88 st.input_format = CoorFormat::ChemComp;
89 if (const std::string* name = block.find_value("_chem_comp.id"))
90 st.name = *name;
91 if (block.has_any_value("_chem_comp_atom.x"))
92 st.models.push_back(
94 if (block.has_any_value("_chem_comp_atom.model_Cartn_x"))
95 st.models.push_back(
97 if (block.has_any_value("_chem_comp_atom.pdbx_model_Cartn_x_ideal"))
98 st.models.push_back(
100 return st;
101}
102
103// a helper function for use with make_structure_from_chemcomp_block():
104// int n = check_chemcomp_block_number(doc);
105// if (n != -1)
106// Structure st = make_structure_from_chemcomp_block(doc.blocks[n]);
108 // monomer library file without global_
109 if (doc.blocks.size() == 2 && doc.blocks[0].name == "comp_list")
110 return 1;
111 // monomer library file with global_
112 if (doc.blocks.size() == 3 && doc.blocks[0].name.empty() &&
113 doc.blocks[1].name == "comp_list")
114 return 2;
115 // CCD file
116 if (doc.blocks.size() == 1 &&
117 !doc.blocks[0].has_tag("_atom_site.id") &&
118 !doc.blocks[0].has_tag("_cell.length_a") &&
119 doc.blocks[0].has_tag("_chem_comp_atom.atom_id"))
120 return 0;
121 return -1;
122}
123
126 if (n == -1)
127 fail("Not a chem_comp format.");
128 return make_structure_from_chemcomp_block(doc.blocks[n]);
129}
130
131} // namespace gemmi
132#endif
int length() const
Definition cifdoc.hpp:248
double as_number(const std::string &s, double nan=NAN)
Definition numb.hpp:19
Model make_model_from_chemcomp_block(const cif::Block &block, ChemCompModel kind)
Structure make_structure_from_chemcomp_block(const cif::Block &block)
int check_chemcomp_block_number(const cif::Document &doc)
Structure make_structure_from_chemcomp_doc(const cif::Document &doc)
bool starts_with(const std::string &str, const std::string &prefix)
Definition util.hpp:38
Residue make_residue_from_chemcomp_block(const cif::Block &block, ChemCompModel kind)
void fail(const std::string &msg)
Definition fail.hpp:59
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
signed char charge
Definition model.hpp:116
Element element
Definition model.hpp:117
Position pos
Definition model.hpp:123
std::string name
Definition model.hpp:114
std::vector< Chain > chains
Definition model.hpp:700
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
std::string name
Definition seqid.hpp:91
std::vector< Atom > atoms
Definition model.hpp:188
OptionalNum num
Definition seqid.hpp:55
std::string name
Definition cifdoc.hpp:444
const std::string * find_value(const std::string &tag) const
Definition cifdoc.hpp:834
bool has_any_value(const std::string &tag) const
Definition cifdoc.hpp:461
size_t length() const
Definition cifdoc.hpp:726