7#ifndef GEMMI_MERGE_HPP_
8#define GEMMI_MERGE_HPP_
24 for (
int i = 0;
i < 3; ++
i) {
25 s += (
i == 0 ?
'(' :
' ');
26 s += std::to_string(hkl[
i]);
34 for (
double* u : {&b.u11, &b.u22, &b.u33, &b.u23, &b.u13, &b.u12}) {
35 if (*start != (first ?
'(' :
','))
39 if (
result.ec != std::errc())
49 "_reflns.pdbx_aniso_B_tensor_eigen",
50 {
"value_1",
"value_2",
"value_3",
51 "vector_1_ortho[1]",
"vector_1_ortho[2]",
"vector_1_ortho[3]",
52 "vector_2_ortho[1]",
"vector_2_ortho[2]",
"vector_2_ortho[3]",
53 "vector_3_ortho[1]",
"vector_3_ortho[2]",
"vector_3_ortho[3]"});
58 double eigval[3] = {as_number(
row[0]), as_number(
row[1]), as_number(
row[2])};
61 as_number(
row[4]), as_number(
row[7]), as_number(
row[10]),
62 as_number(
row[5]), as_number(
row[8]), as_number(
row[11]));
68 output = {
t[0][0],
t[1][1],
t[2][2],
t[0][1],
t[0][2],
t[1][2]};
75 size_t hlen =
mtz.history.size();
76 for (
size_t i = 0;
i !=
hlen; ++
i)
77 if (
mtz.history[
i].find(
"STARANISO") != std::string::npos) {
84 for (
size_t j =
i+1;
j < std::min(
i+4,
hlen); ++
j) {
85 const std::string&
line =
mtz.history[
j];
90 fail(
"failed to parse tensor Voigt notation: " +
line);
113 if (
isign == 0)
return "<I>";
114 if (
isign > 0)
return "I(+)";
132 return std::exp(0.5 *
b.
r_u_r(s));
169 return {{ 1 / std::sqrt(min_1_d2), 1 / std::sqrt(max_1_d2) }};
177 auto r2 = other.
data.begin();
183 }
else if (*
r1 < *
r2) {
212 std::vector<Refl>::iterator
out =
data.begin();
219 out->sigma = 1.0 / std::sqrt(
sum_w);
225 out->isign =
in->isign;
227 double w = 1. / (
in->sigma *
in->sigma);
233 out->sigma = 1.0 / std::sqrt(
sum_w);
257 refl.isign = sign ? 1 : -1;
262 if (
mtz.batches.empty())
263 fail(
"expected unmerged file");
266 fail(
"unmerged file should have M/ISYM as 4th column");
269 size_t sigma_idx =
mtz.get_column_with_label(
"SIGI").idx;
273 fail(
"unknown space group");
275 for (
size_t i = 0;
i <
mtz.data.size();
i +=
mtz.columns.size()) {
276 short isign = ((
int)
mtz.data[
i + 3] % 2 == 0 ? -1 : 1);
286 if (!
mtz.batches.empty())
287 fail(
"expected merged file");
290 fail(
"Mean intensities (IMEAN, I, IOBS or I-obs) not found");
299 if (!
mtz.batches.empty())
300 fail(
"expected merged file");
304 fail(
"anomalous intensities not found");
307 mtz.get_column_with_label(
"SIG" +
colm->label).idx};
319 if (
mtz.column_with_label(
"I(+)"))
343 size_t value_idx =
rb.get_column_index(
"intensity_net");
344 size_t sigma_idx =
rb.get_column_index(
"intensity_sigma");
353 size_t value_idx =
rb.get_column_index(
"intensity_meas");
354 size_t sigma_idx =
rb.get_column_index(
"intensity_sigma");
363 size_t value_idx[2] = {
rb.get_column_index(
"pdbx_I_plus"),
364 rb.get_column_index(
"pdbx_I_minus")};
365 size_t sigma_idx[2] = {
rb.get_column_index(
"pdbx_I_plus_sigma"),
366 rb.get_column_index(
"pdbx_I_minus_sigma")};
369 mean_idx =
rb.find_column_index(
"intensity_meas");
377 if (
rb.find_column_index(
"pdbx_I_plus") != -1)
379 else if (
rb.find_column_index(
"intensity_meas") != -1)
382 fail(
"Intensities not found in the mmCIF file, block ",
rb.block.name,
383 " has neither intensity_meas nor pdbx_I_plus/minus");
391 fail(
"Column F_meas[_au] not found.");
392 int sigma_idx =
rb.find_column_index(
"F_meas_sigma");
394 sigma_idx =
rb.find_column_index(
"F_meas_sigma_au");
396 fail(
"Column F_meas_sigma[_au] not found.");
429 add_if_valid(
in.
hkl, 0,
in.iobs,
in.sigma);
444 template<
typename Source>
445 void copy_metadata(
const Source& source) {
449 fail(
"unknown space group");
452 void add_if_valid(
const Miller& hkl,
short isign,
double value,
double sigma) {
455 if (!std::isnan(value) && sigma > 0)
456 data.push_back({hkl, isign, 0, value, sigma});
459 template<
typename DataProxy>
460 void read_data(
const DataProxy& proxy,
size_t value_idx,
size_t sigma_idx) {
461 for (
size_t i = 0; i < proxy.size(); i += proxy.stride())
462 add_if_valid(proxy.get_hkl(i), 0,
463 proxy.get_num(i + value_idx),
464 proxy.get_num(i + sigma_idx));
467 template<
typename DataProxy>
468 void read_anomalous_data(
const DataProxy& proxy,
int mean_idx,
469 size_t (&value_idx)[2],
size_t (&sigma_idx)[2]) {
471 for (
size_t i = 0; i < proxy.size(); i += proxy.stride()) {
472 Miller hkl = proxy.get_hkl(i);
473 bool centric = gops.is_reflection_centric(hkl);
476 if (mean_idx >= 0 && !std::isnan(proxy.get_num(i + mean_idx)) && !centric) {
477 if (std::isnan(proxy.get_num(i + value_idx[0])) &&
478 std::isnan(proxy.get_num(i + value_idx[1])))
479 fail(
miller_str(hkl),
" has <I>, but I(+) and I(-) are both null");
482 add_if_valid(hkl, 1, proxy.get_num(i + value_idx[0]),
483 proxy.get_num(i + sigma_idx[0]));
485 add_if_valid(hkl, -1, proxy.get_num(i + value_idx[1]),
486 proxy.get_num(i + sigma_idx[1]));
double as_number(const std::string &s, double nan=NAN)
bool parse_voigt_notation(const char *start, const char *end, SMat33< double > &b)
void vector_remove_if(std::vector< T > &v, F &&condition)
std::string read_staraniso_b_from_mtz(const Mtz &mtz, SMat33< double > &output)
bool read_staraniso_b_from_mmcif(const cif::Block &block, SMat33< double > &output)
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
const SpaceGroup * find_spacegroup_by_number(int ccp4) noexcept
from_chars_result fast_from_chars(const char *start, const char *end, double &d)
std::string read_word(const char *line)
std::string miller_str(const Miller &hkl)
bool starts_with(const std::string &str, const std::string &prefix)
void fail(const std::string &msg)
const char * skip_blank(const char *p)
void add_point(double x, double y)
bool is_systematically_absent(const Op::Miller &hkl) const
bool is_reflection_centric(const Op::Miller &hkl) const
double scale(const Miller &hkl, const UnitCell &cell) const
std::string hkl_label() const
bool operator<(const Refl &o) const
const char * intensity_label() const
static const char * type_str(DataType data_type)
void read_merged_intensities_from_mmcif(const ReflnBlock &rb)
bool take_staraniso_b_from_mmcif(const cif::Block &block)
void read_mean_intensities_from_mmcif(const ReflnBlock &rb)
void read_unmerged_intensities_from_xds(const XdsAscii &xds)
void switch_to_asu_indices(bool merged=false)
std::string spacegroup_str() const
void read_anomalous_intensities_from_mtz(const Mtz &mtz, bool check_complete=false)
void merge_in_place(DataType data_type)
std::string take_staraniso_b_from_mtz(const Mtz &mtz)
void remove_systematic_absences()
void read_merged_intensities_from_mtz(const Mtz &mtz)
const char * type_str() const
void read_anomalous_intensities_from_mmcif(const ReflnBlock &rb, bool check_complete=false)
void read_mtz(const Mtz &mtz, DataType data_type)
std::array< double, 2 > resolution_range() const
void read_unmerged_intensities_from_mtz(const Mtz &mtz)
void read_unmerged_intensities_from_mmcif(const ReflnBlock &rb)
Correlation calculate_correlation(const Intensities &other) const
void read_mean_intensities_from_mtz(const Mtz &mtz)
void read_mmcif(const ReflnBlock &rb, DataType data_type)
void read_f_squared_from_mmcif(const ReflnBlock &rb)
const SpaceGroup * spacegroup
Vec3 left_multiply(const Vec3 &p) const
Mat33 multiply_by_diagonal(const Vec3 &p) const
Vec3 multiply(const Vec3 &p) const
std::pair< Op::Miller, bool > to_asu_sign(const Op::Miller &hkl, const GroupOps &gops) const
Similar to to_asu(), but the second returned value is sign: true for + or centric.
bool is_in(const Op::Miller &hkl) const
auto r_u_r(const Vec3_< VT > &r) const -> decltype(r.x+u11)
double calculate_1_d2(const Miller &hkl) const