Gemmi C++ API
Loading...
Searching...
No Matches
xds_ascii.hpp
Go to the documentation of this file.
1// Copyright 2020 Global Phasing Ltd.
2//
3// Read XDS files: XDS_ASCII.HKL and INTEGRATE.HKL.
4
5#ifndef GEMMI_XDS_ASCII_HPP_
6#define GEMMI_XDS_ASCII_HPP_
7
8#include "input.hpp" // for AnyStream, FileStream
9#include "unitcell.hpp" // for UnitCell
10#include "util.hpp" // for starts_with
11
12namespace gemmi {
13
14// from Pointless docs: likely in-house source, in which case
15// the unpolarised value is left unchanged (recognised wavelengths
16// are CuKalpha 1.5418 +- 0.0019, Mo 0.7107 +- 0.0002, Cr 2.29 +- 0.01)
17inline bool likely_in_house_source(double wavelength) {
18 return std::fabs(wavelength - 1.5418) < 0.0019 ||
19 std::fabs(wavelength - 0.7107) < 0.0002 ||
20 std::fabs(wavelength - 2.29) < 0.01;
21}
22
24 struct Iset {
25 int id;
26 std::string input_file;
27 double wavelength = 0.;
28 std::array<double,6> cell_constants = {0., 0., 0., 0., 0., 0.};
29 //statistics set by gather_iset_statistics()
32 int frame_count = -1;
34
35 Iset(int id_) : id(id_) {}
36 };
37 std::string source_path;
38 int read_columns = 0; // doesn't include ITEM_ISET from XSCALE
40 double wavelength = 0.;
41 std::array<double,6> cell_constants = {0., 0., 0., 0., 0., 0.};
44 double oscillation_range = 0.;
46 double starting_angle = 0.;
48 char friedels_law = '\0';
50 int nx = 0; // detector size - number of pixels
51 int ny = 0;
52 double qx = 0.; // pixel size in mm
53 double qy = 0.;
54 double orgx = 0.;
55 double orgy = 0.;
56 double detector_distance = 0.;
57 std::string generated_by;
58 std::string version_str;
59 std::vector<Iset> isets;
60};
61
63 struct Refl {
65 int iset = 1;
66 double iobs;
67 double sigma;
68 double xd;
69 double yd;
70 double zd;
71 double rlp;
72 double peak;
73 double corr; // is it always integer?
74 double maxc;
75
76 // ZD can be negative for a few reflections
77 int frame() const { return (int) std::floor(zd + 1); }
78 };
79 std::vector<Refl> data;
80
81 XdsAscii() = default;
83
85 for (Iset& i : isets)
86 if (i.id == id)
87 return i;
88 isets.emplace_back(id);
89 return isets.back();
90 }
91 void read_stream(AnyStream& reader, const std::string& source);
92
93 template<typename T>
94 void read_input(T&& input) {
95 read_stream(*input.create_stream(), input.path());
96 }
97
98 bool is_merged() const { return read_columns < 8; }
99
100 // set a few Iset properties in isets
102
103 double rot_angle(const Refl& refl) const {
104 double z = refl.zd - starting_frame + 1;
105 return starting_angle + oscillation_range * z;
106 }
107
108 // it's already normalized, but just in case normalize it again
110 double length = rotation_axis.length();
111 if (length == 0)
112 fail("unknown rotation axis");
113 return rotation_axis / length;
114 }
115
116 // I'm not sure if always |incident_beam_dir| == 1/wavelength
118 double length = incident_beam_dir.length();
119 if (length == 0)
120 fail("unknown incident beam direction");
121 return incident_beam_dir / length;
122 }
123
124 bool has_cell_axes() const {
125 for (int i = 0; i < 3; ++i)
126 if (cell_axes[i][0] == 0 && cell_axes[i][1] == 0 && cell_axes[i][2] == 0)
127 return false;
128 return true;
129 }
130
134 // Cambridge z direction is along the principal rotation axis
135 Vec3 z = get_rotation_axis();
136 // Cambridge z direction is along beam
137 Vec3 x = get_s0_direction();
138 Vec3 y = z.cross(x).normalized();
139 // beam and rotation axis may not be orthogonal
140 x = y.cross(z).normalized();
141 return Mat33::from_columns(x, y, z);
142 }
143
145 if (!has_cell_axes())
146 fail("unknown unit cell axes");
147 Vec3 a = cell_axes.row_copy(0);
148 Vec3 b = cell_axes.row_copy(1);
149 Vec3 c = cell_axes.row_copy(2);
150 Vec3 ar = b.cross(c).normalized();
151 Vec3 br = c.cross(a);
152 Vec3 cr = ar.cross(br).normalized();
153 br = cr.cross(ar);
154 return Mat33::from_columns(ar, br, cr);
155 }
156
159
162 vector_remove_if(data, [&](Refl& r) { return r.maxc > overload; });
163 }
164
167 double minz = batchmin - 1;
168 vector_remove_if(data, [&](Refl& r) { return r.zd < minz; });
169 }
170};
171
172inline XdsAscii read_xds_ascii_file(const std::string& path) {
174 FileStream stream(path.c_str(), "rb");
175 ret.read_stream(stream, path);
176 return ret;
177}
178
180GEMMI_DLL XdsAscii read_xds_ascii(const std::string& path);
181
182} // namespace gemmi
183#endif
#define GEMMI_DLL
Definition fail.hpp:53
Input abstraction. Used to decouple file reading and decompression.
void vector_remove_if(std::vector< T > &v, F &&condition)
Definition util.hpp:267
GEMMI_DLL XdsAscii read_xds_ascii(const std::string &path)
read possibly gzipped file
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:129
Vec3_< double > Vec3
Definition math.hpp:113
bool likely_in_house_source(double wavelength)
Definition xds_ascii.hpp:17
void fail(const std::string &msg)
Definition fail.hpp:59
XdsAscii read_xds_ascii_file(const std::string &path)
std::array< double, 6 > cell_constants
Definition xds_ascii.hpp:28
std::array< double, 6 > cell_constants
Definition xds_ascii.hpp:41
std::vector< Iset > isets
Definition xds_ascii.hpp:59
Vec3 get_rotation_axis() const
Vec3 get_s0_direction() const
bool has_cell_axes() const
void read_stream(AnyStream &reader, const std::string &source)
Mat33 calculate_conversion_from_cambridge() const
Return transition matrix from "Cambridge" frame to XDS frame.
Mat33 get_orientation() const
double rot_angle(const Refl &refl) const
XdsAscii(const XdsAsciiMetadata &m)
Definition xds_ascii.hpp:82
void gather_iset_statistics()
void eliminate_overloads(double overload)
XdsAscii()=default
std::vector< Refl > data
Definition xds_ascii.hpp:79
void apply_polarization_correction(double p, Vec3 normal)
Iset & find_or_add_iset(int id)
Definition xds_ascii.hpp:84
bool is_merged() const
Definition xds_ascii.hpp:98
void eliminate_batchmin(int batchmin)
void read_input(T &&input)
Definition xds_ascii.hpp:94
Unit cell.
Utilities. Mostly for working with strings and vectors.