hkl_key: Dedicated header

This commit is contained in:
2026-01-22 12:03:46 +01:00
parent 6f653866e3
commit 8c7bf61fa7
6 changed files with 83 additions and 10 deletions

View File

@@ -121,6 +121,7 @@ ADD_LIBRARY(JFJochCommon STATIC
DarkMaskSettings.h
TopPixels.cpp
TopPixels.h
hkl_key.h
)
TARGET_LINK_LIBRARIES(JFJochCommon JFJochLogger Compression JFCalibration gemmi Threads::Threads -lrt )

39
common/hkl_key.h Normal file
View File

@@ -0,0 +1,39 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
# pragma once
#include <cstdint>
#include "JFJochException.h"
constexpr int64_t bias = 512;
inline uint64_t encode(int64_t v) {
const int64_t tmp = v + bias;
if (tmp < 0 || tmp >= 2 * bias)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Value out of range");
return static_cast<uint64_t>(tmp);
}
inline uint64_t hkl_key(const int64_t h, const int64_t k, const int64_t l) {
const uint64_t uh = encode(h);
const uint64_t uk = encode(k);
const uint64_t ul = encode(l);
return uh | (uk << 11) | (ul << 22);
}
inline int64_t decode(uint64_t v) {
if (v >= 2 * bias)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Value out of range");
return static_cast<int64_t>(v) - bias;
}
inline void hkl_from_key(uint64_t key, int64_t& h, int64_t& k, int64_t& l) {
constexpr uint64_t mask = (1ULL << 11) - 1;
const uint64_t uh = (key >> 0) & mask;
const uint64_t uk = (key >> 11) & mask;
const uint64_t ul = (key >> 22) & mask;
h = decode(uh);
k = decode(uk);
l = decode(ul);
}

View File

@@ -63,6 +63,7 @@ ADD_EXECUTABLE(jfjoch_test
TimeTest.cpp
RotationIndexerTest.cpp
TopPixelsTest.cpp
HKLKeyTest.cpp
)
target_link_libraries(jfjoch_test Catch2WithMain JFJochBroker JFJochReceiver JFJochReader JFJochWriter JFJochImageAnalysis JFJochCommon JFJochHLSSimulation JFJochPreview)

40
tests/HKLKeyTest.cpp Normal file
View File

@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <catch2/catch_all.hpp>
#include "../common/hkl_key.h"
TEST_CASE("HKL key round-trip", "[hkl_key]") {
struct Case { int64_t h, k, l; };
const Case cases[] = {
{0, 0, 0},
{1, -2, 3},
{-511, 0, 511},
{512 - 1, -(512 - 1), 7},
{-128, 255, -7}
};
for (const auto& c : cases) {
const uint64_t key = hkl_key(c.h, c.k, c.l);
int64_t h = 0, k = 0, l = 0;
hkl_from_key(key, h, k, l);
CHECK(h == c.h);
CHECK(k == c.k);
CHECK(l == c.l);
}
}
TEST_CASE("HKL key boundaries", "[hkl_key]") {
const int64_t min = -512;
const int64_t max = 511;
const uint64_t key = hkl_key(min, 0, max);
int64_t h = 0, k = 0, l = 0;
hkl_from_key(key, h, k, l);
CHECK(h == min);
CHECK(k == 0);
CHECK(l == max);
}

View File

@@ -8,6 +8,7 @@
#include <stdexcept>
#include "../common/ResolutionShells.h"
#include "../common/hkl_key.h"
IntegrateMap ParseXdsIntegrateHkl(const std::string& filename) {
std::ifstream in(filename);
@@ -47,7 +48,7 @@ IntegrateMap ParseXdsIntegrateHkl(const std::string& filename) {
entry.tail.push_back(v);
}
result[hkl_key_16(-h, k, l)].push_back(std::move(entry));
result[hkl_key(-h, k, l)].push_back(std::move(entry));
}
return result;

View File

@@ -12,21 +12,12 @@
#include "../common/CrystalLattice.h"
struct CcHalfByResolutionResult {
std::vector<double> cc;
std::vector<int32_t> pairs;
std::vector<float> shell_mean_one_over_d2;
};
inline uint64_t hkl_key_16(int64_t h, int64_t k, int64_t l) {
const uint16_t bias = 512; // maps -512..512 -> 0..1024
uint64_t uh = static_cast<uint16_t>(std::clamp(h + bias, int64_t(0), int64_t(1024)));
uint64_t uk = static_cast<uint16_t>(std::clamp(k + bias, int64_t(0), int64_t(1024)));
uint64_t ul = static_cast<uint16_t>(std::clamp(l + bias, int64_t(0), int64_t(1024)));
return uh | (uk << 16) | (ul << 32);
}
struct HKLData {
int64_t h ,k,l;
double I = 0.0;