Gemmi C++ API
Loading...
Searching...
No Matches
refln.hpp
Go to the documentation of this file.
1// Copyright 2019 Global Phasing Ltd.
2//
3// Reads reflection data from the mmCIF format.
4
5#ifndef GEMMI_REFLN_HPP_
6#define GEMMI_REFLN_HPP_
7
8#include <array>
9#include "cifdoc.hpp"
10#include "fail.hpp" // for fail
11#include "mmcif_impl.hpp" // for set_cell_from_mmcif, read_spacegroup_from_block
12#include "numb.hpp" // for as_number
13#include "symmetry.hpp" // for SpaceGroup
14#include "unitcell.hpp" // for UnitCell
15
16namespace gemmi {
17
19
20struct ReflnBlock {
22 std::string entry_id;
24 const SpaceGroup* spacegroup = nullptr;
25 double wavelength;
30
31 ReflnBlock() = default;
35 impl::set_cell_from_mmcif(block, cell);
36 if (const std::string* hm = impl::find_spacegroup_hm_value(block))
40 const char* wave_tag = "_diffrn_radiation_wavelength.wavelength";
42 wavelength_count = wave_col.length();
44 refln_loop = block.find_loop("_refln.index_h").get_loop();
45 diffrn_refln_loop = block.find_loop("_diffrn_refln.index_h").get_loop();
47 }
50 block = o.block;
51 entry_id = o.entry_id;
52 cell = o.cell;
53 spacegroup = o.spacegroup;
54 wavelength = o.wavelength;
55 wavelength_count = o.wavelength_count;
56 if (o.refln_loop)
57 refln_loop = block.find_loop("_refln.index_h").get_loop();
58 if (o.diffrn_refln_loop)
59 diffrn_refln_loop = block.find_loop("_diffrn_refln.index_h").get_loop();
61 return *this;
62 }
63
64 bool ok() const { return default_loop != nullptr; }
65 void check_ok() const { if (!ok()) fail("Invalid ReflnBlock"); }
66
67 // position after "_refln." or "_diffrn_refln."
68 size_t tag_offset() const { return refln_loop ? 7 : 14; }
69
73 bool is_unmerged() const { return ok() && default_loop == diffrn_refln_loop; }
74
75 std::vector<std::string> column_labels() const {
76 check_ok();
77 std::vector<std::string> labels(default_loop->tags.size());
78 for (size_t i = 0; i != labels.size(); ++i)
79 labels[i].assign(default_loop->tags[i], tag_offset(), std::string::npos);
80 return labels;
81 }
82
83 int find_column_index(const std::string& tag) const {
84 if (!ok())
85 return -1;
86 size_t name_pos = tag_offset();
87 for (int i = 0; i != (int) default_loop->tags.size(); ++i)
88 if (default_loop->tags[i].compare(name_pos, std::string::npos, tag) == 0)
89 return i;
90 return -1;
91 }
92
93 size_t get_column_index(const std::string& tag) const {
94 int idx = find_column_index(tag);
95 if (idx == -1)
96 fail("Column not found: " + tag);
97 return idx;
98 }
99
100 template<typename T>
101 std::vector<T> make_vector(const std::string& tag, T null) const {
102 size_t n = get_column_index(tag);
103 std::vector<T> v(default_loop->length());
104 for (size_t j = 0; j != v.size(); n += default_loop->width(), ++j)
106 return v;
107 }
108
109 std::array<size_t,3> get_hkl_column_indices() const {
110 return {{get_column_index("index_h"),
111 get_column_index("index_k"),
112 get_column_index("index_l")}};
113 }
114
115 std::vector<Miller> make_miller_vector() const {
117 std::vector<Miller> v(default_loop->length());
118 for (size_t j = 0, n = 0; j != v.size(); j++, n += default_loop->width())
119 for (int i = 0; i != 3; ++i)
120 v[j][i] = cif::as_int(default_loop->values[n + hkl_idx[i]]);
121 return v;
122 }
123
124 std::vector<double> make_1_d2_vector() const {
125 if (!cell.is_crystal() || cell.a <= 0)
126 fail("Unit cell is not known");
128 std::vector<double> r(default_loop->length());
129 for (size_t j = 0, n = 0; j != r.size(); j++, n += default_loop->width()) {
130 Miller hkl;
131 for (int i = 0; i != 3; ++i)
132 hkl[i] = cif::as_int(default_loop->values[n + hkl_idx[i]]);
133 r[j] = cell.calculate_1_d2(hkl);
134 }
135 return r;
136 }
137
138 std::vector<double> make_d_vector() const {
139 std::vector<double> vec = make_1_d2_vector();
140 for (double& d : vec)
141 d = 1.0 / std::sqrt(d);
142 return vec;
143 }
144};
145
146// moves blocks from the argument to the return value
147inline
148std::vector<ReflnBlock> as_refln_blocks(std::vector<cif::Block>&& blocks) {
149 std::vector<ReflnBlock> rvec;
150 rvec.reserve(blocks.size());
151 for (cif::Block& block : blocks)
152 rvec.emplace_back(std::move(block));
153 blocks.clear();
154 // Some blocks miss space group or unit cell, try to fill it in.
155 const SpaceGroup* first_sg = nullptr;
156 const UnitCell* first_cell = nullptr;
157 for (ReflnBlock& rblock : rvec) {
158 if (!first_sg)
159 first_sg = rblock.spacegroup;
160 else if (!rblock.spacegroup)
161 rblock.spacegroup = first_sg;
162 if (rblock.cell.is_crystal()) {
163 if (!first_cell)
164 first_cell = &rblock.cell;
165 } else if (first_cell) {
166 rblock.cell = *first_cell;
167 }
168 }
169 return rvec;
170}
171
172// Get the first (merged) block with required labels.
173// Optionally, block name can be specified.
174inline ReflnBlock get_refln_block(std::vector<cif::Block>&& blocks,
175 const std::vector<std::string>& labels,
176 const char* block_name=nullptr) {
177 const SpaceGroup* first_sg = nullptr;
178 for (cif::Block& block : blocks) {
179 if (!first_sg)
180 if (const std::string* hm = impl::find_spacegroup_hm_value(block)) {
182 if (first_sg && first_sg->ext == 'H') {
183 UnitCell cell;
184 impl::set_cell_from_mmcif(block, cell);
186 cell.alpha, cell.gamma);
187 }
188 }
189 if (block_name && block.name != block_name)
190 continue;
191 if (cif::Loop* loop = block.find_loop("_refln.index_h").get_loop())
192 if (std::all_of(labels.begin(), labels.end(),
193 [&](const std::string& s) { return loop->has_tag("_refln."+s); })) {
194 ReflnBlock rblock(std::move(block));
195 if (!rblock.spacegroup && first_sg)
196 rblock.spacegroup = first_sg;
197 return rblock;
198 }
199 }
200 fail("Required block or tags not found in the SF-mmCIF file.");
201}
202
205 rb.block.swap(block);
206 rb.entry_id = rb.block.name;
207 impl::set_cell_from_mmcif(rb.block, rb.cell, /*mmcif=*/false);
208 const char* hm_tag = "_symmetry_space_group_name_H-M";
209 if (const std::string* hm = rb.block.find_value(hm_tag))
210 rb.spacegroup = find_spacegroup_by_name(cif::as_string(*hm),
211 rb.cell.alpha, rb.cell.gamma);
212 rb.cell.set_cell_images_from_spacegroup(rb.spacegroup);
213 rb.refln_loop = rb.block.find_loop("_refln_index_h").get_loop();
214 rb.default_loop = rb.refln_loop;
215 return rb;
216}
217
218// Abstraction of data source, cf. MtzDataProxy.
220 const ReflnBlock& rb_;
221 std::array<size_t,3> hkl_cols_;
222 explicit ReflnDataProxy(const ReflnBlock& rb)
223 : rb_(rb), hkl_cols_(rb_.get_hkl_column_indices()) {}
224 size_t stride() const { return loop().tags.size(); }
225 size_t size() const { return loop().values.size(); }
227 double get_num(size_t n) const { return cif::as_number(loop().values[n]); }
228 const UnitCell& unit_cell() const { return rb_.cell; }
229 const SpaceGroup* spacegroup() const { return rb_.spacegroup; }
230 Miller get_hkl(size_t offset) const {
231 return {{get_int(offset + hkl_cols_[0]),
232 get_int(offset + hkl_cols_[1]),
233 get_int(offset + hkl_cols_[2])}};
234 }
235 size_t column_index(const std::string& label) const { return rb_.get_column_index(label); }
236private:
237 const cif::Loop& loop() const { rb_.check_ok(); return *rb_.default_loop; }
238 int get_int(size_t n) const { return cif::as_int(loop().values[n]); }
239};
240
242
243} // namespace gemmi
244#endif
Loop * get_loop() const
Definition cifdoc.hpp:674
int as_any(const std::string &s, int null)
Definition cifdoc.hpp:117
double as_number(const std::string &s, double nan=NAN)
Definition numb.hpp:19
std::string as_string(const std::string &value)
Definition cifdoc.hpp:81
int as_int(const std::string &str)
Definition cifdoc.hpp:108
DataType
Definition refln.hpp:18
MtzDataProxy data_proxy(const Mtz &mtz)
Definition mtz.hpp:1096
std::vector< ReflnBlock > as_refln_blocks(std::vector< cif::Block > &&blocks)
Definition refln.hpp:148
ReflnBlock hkl_cif_as_refln_block(cif::Block &block)
Definition refln.hpp:203
const SpaceGroup * find_spacegroup_by_name(std::string name, double alpha=0., double gamma=0.) noexcept
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:128
ReflnBlock get_refln_block(std::vector< cif::Block > &&blocks, const std::vector< std::string > &labels, const char *block_name=nullptr)
Definition refln.hpp:174
void fail(const std::string &msg)
Definition fail.hpp:59
Definition seqid.hpp:149
int find_column_index(const std::string &tag) const
Definition refln.hpp:83
size_t tag_offset() const
Definition refln.hpp:68
std::vector< T > make_vector(const std::string &tag, T null) const
Definition refln.hpp:101
UnitCell cell
Definition refln.hpp:23
void use_unmerged(bool unmerged)
Definition refln.hpp:70
cif::Loop * default_loop
Definition refln.hpp:29
std::string entry_id
Definition refln.hpp:22
bool ok() const
Definition refln.hpp:64
cif::Loop * refln_loop
Definition refln.hpp:27
double wavelength
Definition refln.hpp:25
void check_ok() const
Definition refln.hpp:65
ReflnBlock & operator=(const ReflnBlock &o)
Definition refln.hpp:49
std::vector< Miller > make_miller_vector() const
Definition refln.hpp:115
cif::Loop * diffrn_refln_loop
Definition refln.hpp:28
ReflnBlock & operator=(ReflnBlock &&)=default
const SpaceGroup * spacegroup
Definition refln.hpp:24
bool is_unmerged() const
Definition refln.hpp:73
size_t get_column_index(const std::string &tag) const
Definition refln.hpp:93
std::vector< double > make_d_vector() const
Definition refln.hpp:138
ReflnBlock(cif::Block &&block_)
Definition refln.hpp:33
std::array< size_t, 3 > get_hkl_column_indices() const
Definition refln.hpp:109
ReflnBlock(ReflnBlock &&rblock_)=default
cif::Block block
Definition refln.hpp:21
ReflnBlock()=default
std::vector< double > make_1_d2_vector() const
Definition refln.hpp:124
std::vector< std::string > column_labels() const
Definition refln.hpp:75
ReflnDataProxy(const ReflnBlock &rb)
Definition refln.hpp:222
Miller get_hkl(size_t offset) const
Definition refln.hpp:230
size_t stride() const
Definition refln.hpp:224
size_t size() const
Definition refln.hpp:225
double get_num(size_t n) const
Definition refln.hpp:227
const UnitCell & unit_cell() const
Definition refln.hpp:228
const SpaceGroup * spacegroup() const
Definition refln.hpp:229
size_t column_index(const std::string &label) const
Definition refln.hpp:235
Unit cell.
Definition unitcell.hpp:139
bool is_crystal() const
Definition unitcell.hpp:164
double calculate_1_d2(const Miller &hkl) const
Definition unitcell.hpp:529
void set_cell_images_from_spacegroup(const SpaceGroup *sg)
Definition unitcell.hpp:337
Column find_values(const std::string &tag)
Definition cifdoc.hpp:848
Column find_loop(const std::string &tag)
Definition cifdoc.hpp:821
const std::string * find_value(const std::string &tag) const
Definition cifdoc.hpp:834
size_t width() const
Definition cifdoc.hpp:142
std::vector< std::string > tags
Definition cifdoc.hpp:129
std::vector< std::string > values
Definition cifdoc.hpp:130
size_t length() const
Definition cifdoc.hpp:143