v1.0.0-rc.40

This commit is contained in:
2025-05-28 18:49:27 +02:00
parent aaae74e70b
commit 53c90ee5d8
340 changed files with 9583 additions and 5919 deletions

View File

@@ -109,6 +109,21 @@ namespace {
return map_len;
}
Coord GetCoord(CborValue &value) {
CborValue array_value;
Coord c;
if (GetCBORArrayLen(value) != 3)
throw JFJochException(JFJochExceptionCategory::CBORError, "Vector of 3 elements expected");
cborErr(cbor_value_enter_container(&value, &array_value));
c.x = GetCBORFloat(array_value);
c.y = GetCBORFloat(array_value);
c.z = GetCBORFloat(array_value);
cborErr(cbor_value_leave_container(&value, &array_value));
return c;
}
std::pair<uint64_t, uint64_t> GetRational(CborValue &value) {
std::pair<uint64_t, uint64_t> ret;
if (GetCBORArrayLen(value) != 2)
@@ -168,21 +183,15 @@ namespace {
return unit_cell;
}
std::pair<uint64_t, uint64_t> GetCBORDimension2DArray(CborValue &value) {
std::pair<uint64_t, uint64_t> ret;
if (GetCBORArrayLen(value) != 2)
throw JFJochException(JFJochExceptionCategory::CBORError, "Only 2D arrays allowed");
std::vector<uint64_t> GetCBORDimensionArray(CborValue &value) {
std::vector<uint64_t> ret;
CborValue array_value;
cborErr(cbor_value_enter_container(&value, &array_value));
ret.second = GetCBORUInt(array_value);
ret.first = GetCBORUInt(array_value);
while (!cbor_value_at_end(&array_value))
ret.push_back(GetCBORUInt(array_value));
cborErr(cbor_value_leave_container(&value, &array_value));
return ret;
}
@@ -256,49 +265,38 @@ namespace {
memcpy(v.data(), ptr, len);
}
void GetCBORTypedArray(CompressedImage &v, CborValue &value) {
CborTag tag = GetCBORTag(value);
switch (tag) {
CompressedImageMode GetImageMode(CborTag input) {
switch (input) {
case TagHalfLE:
return CompressedImageMode::Float16;
case TagFloatLE:
v.pixel_is_signed = true;
v.pixel_depth_bytes = sizeof(float);
v.pixel_is_float = true;
break;
return CompressedImageMode::Float32;
case TagDoubleLE:
return CompressedImageMode::Float64;
case TagSignedInt8Bit:
v.pixel_is_signed = true;
v.pixel_depth_bytes = 1;
v.pixel_is_float = false;
break;
return CompressedImageMode::Int8;
case TagUnsignedInt8Bit:
v.pixel_is_signed = false;
v.pixel_depth_bytes = 1;
v.pixel_is_float = false;
break;
return CompressedImageMode::Uint8;
case TagSignedInt16BitLE:
v.pixel_is_signed = true;
v.pixel_depth_bytes = 2;
v.pixel_is_float = false;
break;
return CompressedImageMode::Int16;
case TagUnsignedInt16BitLE:
v.pixel_is_signed = false;
v.pixel_depth_bytes = 2;
v.pixel_is_float = false;
break;
return CompressedImageMode::Uint16;
case TagSignedInt32BitLE:
v.pixel_is_signed = true;
v.pixel_depth_bytes = 4;
v.pixel_is_float = false;
break;
return CompressedImageMode::Int32;
case TagUnsignedInt32BitLE:
v.pixel_is_signed = false;
v.pixel_depth_bytes = 4;
v.pixel_is_float = false;
break;
return CompressedImageMode::Uint32;
default:
throw JFJochException(JFJochExceptionCategory::CBORError,
"Only int/uint arrays of 1, 2, 4 bytes per element allowed");
}
}
CompressedImage GetCBORTypedArray(CborValue &value, const std::vector<uint64_t> &dim) {
CompressedImageMode mode = GetImageMode(GetCBORTag(value));
CompressionAlgorithm algorithm = CompressionAlgorithm::NO_COMPRESSION;
size_t xpixel, ypixel;
size_t size;
const uint8_t *ptr = nullptr;
if (cbor_value_is_tag(&value)) {
if (GetCBORTag(value) != TagDECTRISCompression)
@@ -313,29 +311,41 @@ namespace {
auto algorithm_text = GetCBORString(array_value);
if (algorithm_text == "bslz4")
v.algorithm = CompressionAlgorithm::BSHUF_LZ4;
algorithm = CompressionAlgorithm::BSHUF_LZ4;
else if (algorithm_text == "bszstd")
v.algorithm = CompressionAlgorithm::BSHUF_ZSTD;
algorithm = CompressionAlgorithm::BSHUF_ZSTD;
else
throw JFJochException(JFJochExceptionCategory::CBORError, "Unsupported compression algorithm");
v.pixel_depth_bytes = GetCBORUInt(array_value);
auto pixel_depth_bytes = GetCBORUInt(array_value);
auto ret = GetCBORByteString(array_value);
v.data = ret.first;
v.size = ret.second;
ptr = ret.first;
size = ret.second;
cborErr(cbor_value_leave_container(&value, &array_value));
} else if (cbor_value_is_byte_string(&value)) {
v.algorithm = CompressionAlgorithm::NO_COMPRESSION;
algorithm = CompressionAlgorithm::NO_COMPRESSION;
auto ret = GetCBORByteString(value);
v.data = ret.first;
v.size = ret.second;
ptr = ret.first;
size = ret.second;
} else
throw JFJochException(JFJochExceptionCategory::CBORError, "Byte string or compressed array expected");
if (dim.size() == 2) {
xpixel = dim[1];
ypixel = dim[0];
} else if (dim.size() == 3 && dim[0] == 3 && mode == CompressedImageMode::Uint8) {
mode = CompressedImageMode::RGB;
xpixel = dim[2];
ypixel = dim[1];
} else
throw JFJochException(JFJochExceptionCategory::CBORError, "Image dimension not supported");
return CompressedImage(ptr, size, xpixel, ypixel, mode, algorithm);
}
void GetCBORMultidimTypedArray(CompressedImage &v, CborValue &value) {
CompressedImage GetCBORMultidimTypedArray(CborValue &value) {
if (GetCBORTag(value) != TagMultiDimArray)
throw JFJochException(JFJochExceptionCategory::CBORError, "Multidim array expected");
@@ -346,13 +356,12 @@ namespace {
CborValue array_value;
cborErr(cbor_value_enter_container(&value, &array_value));
auto [x, y] = GetCBORDimension2DArray(array_value);
v.xpixel = x;
v.ypixel = y;
GetCBORTypedArray(v, array_value);
auto dim = GetCBORDimensionArray(array_value);
CompressedImage image = GetCBORTypedArray(array_value, dim);
cborErr(cbor_value_leave_container(&value, &array_value));
return image;
}
void CheckMagicNumber(CborValue &v) {
@@ -361,7 +370,7 @@ namespace {
"Inconsistency between Jungfraujoch server and writer");
}
void ProcessImageData(CborValue &value, CompressedImage &image) {
CompressedImage ProcessImageData(CborValue &value) {
if (!cbor_value_is_map(&value))
throw JFJochException(JFJochExceptionCategory::CBORError, "Map expected");
@@ -373,10 +382,12 @@ namespace {
cborErr(cbor_value_enter_container(&value, &map_value));
image.channel = GetCBORString(map_value);
GetCBORMultidimTypedArray(image, map_value);
std::string channel = GetCBORString(map_value);
CompressedImage image = GetCBORMultidimTypedArray(map_value);
image.Channel(channel);
cborErr(cbor_value_leave_container(&value, &map_value));
return image;
}
// Data message
@@ -489,7 +500,7 @@ namespace {
else if (key == "original_image_id")
message.original_number = GetCBORInt(value);
else if (key == "data")
ProcessImageData(value, message.image);
message.image = ProcessImageData(value);
else if (key == "series_unique_id")
message.run_name = GetCBORString(value);
else if (key == "series_id")
@@ -519,6 +530,8 @@ namespace {
message.indexing_result = GetCBORBool(value);
else if (key == "indexing_lattice")
GetCBORFloatArray(value, message.indexing_lattice);
else if (key == "indexing_time")
message.indexing_time_s = GetCBORFloat(value);
else if (key == "indexing_unit_cell")
message.indexing_unit_cell = ProcessUnitCellElement(value);
else if (key == "jf_info")
@@ -628,9 +641,48 @@ namespace {
cborErr(cbor_value_leave_container(&value, &array_value));
}
GoniometerAxis ProcessGoniometerOmega(std::string &name, CborValue &value) {
GoniometerAxis ret{};
ret.name = name;
std::optional<GridScanSettings> ProcessGridScan(CborValue &value) {
int64_t n_fast = 0;
int64_t n_slow = 0;
float step_x_um = 0;
float step_y_um = 0;
bool snake = false;
bool vertical = false;
CborValue map_value;
cborErr(cbor_value_enter_container(&value, &map_value));
while (!cbor_value_at_end(&map_value)) {
auto key = GetCBORString(map_value);
if (key == "n_fast")
n_fast = GetCBORInt(map_value);
else if (key == "n_slow")
n_slow = GetCBORInt(map_value);
else if (key == "step_x_axis")
step_x_um = GetCBORFloat(map_value) * 1e6f;
else if (key == "step_y_axis")
step_y_um = GetCBORFloat(map_value) * 1e6f;
else if (key == "snake_scan")
snake = GetCBORBool(map_value);
else if (key == "vertical_scan")
vertical = GetCBORBool(map_value);
else
cbor_value_advance(&map_value);
}
cborErr(cbor_value_leave_container(&value, &map_value));
GridScanSettings grid(n_fast, step_x_um, step_y_um,
snake, vertical);
grid.ImageNum(n_fast * n_slow);
return grid;
}
std::optional<GoniometerAxis> ProcessGoniometer(std::string &name, CborValue &value) {
float start = 0;
float increment = 1;
Coord axis = {1,0,0};
std::optional<Coord> helical;
CborValue map_value;
@@ -638,15 +690,22 @@ namespace {
while (!cbor_value_at_end(&map_value)) {
auto key = GetCBORString(map_value);
if (key == "increment")
ret.increment = GetCBORFloat(map_value);
increment = GetCBORFloat(map_value);
else if (key == "start")
ret.start = GetCBORFloat(map_value);
start = GetCBORFloat(map_value);
else if (key == "axis")
axis = GetCoord(map_value);
else if (key == "helical_step")
helical = GetCoord(map_value);
else
cbor_value_advance(&value);
cbor_value_advance(&map_value);
}
cborErr(cbor_value_leave_container(&value, &map_value));
return ret;
if (increment == 0)
return {};
else
return GoniometerAxis(name, start, increment, axis, helical);
}
void ProcessROIConfig(StartMessage &message, const nlohmann::json &j) {
@@ -692,9 +751,8 @@ namespace {
cborErr(cbor_value_enter_container(&value, &map_value));
while (!cbor_value_at_end(&map_value)) {
GoniometerAxis axis;
auto key = GetCBORString(map_value);
message.goniometer = ProcessGoniometerOmega(key, map_value);
message.goniometer = ProcessGoniometer(key, map_value);
}
cborErr(cbor_value_leave_container(&value, &map_value));
}
@@ -706,16 +764,16 @@ namespace {
cborErr(cbor_value_enter_container(&value, &map_value));
while (!cbor_value_at_end(&map_value)) {
auto key = GetCBORString(map_value);
CompressedImage image;
image.channel = key;
GetCBORMultidimTypedArray(image, map_value);
CompressedImage image = GetCBORMultidimTypedArray(map_value);
image.Channel(key);
if (image.pixel_is_float || image.pixel_is_signed || (image.pixel_depth_bytes != sizeof(uint32_t)))
if (image.GetMode() != CompressedImageMode::Uint32)
continue;
std::vector<uint32_t> mask_uncompressed;
JFJochDecompress(mask_uncompressed, image.algorithm, image.data, image.size,
image.xpixel * image.ypixel);
JFJochDecompress(mask_uncompressed, image.GetCompressionAlgorithm(),
image.GetCompressed(), image.GetCompressedSize(),
image.GetWidth() * image.GetHeight());
message.pixel_mask[key] = mask_uncompressed;
}
cborErr(cbor_value_leave_container(&value, &map_value));
@@ -759,11 +817,6 @@ namespace {
message.total_flux = j["total_flux"];
if (j.contains("attenuator_transmission"))
message.attenuator_transmission = j["attenuator_transmission"];
if (j.contains("rotation_axis") && j["rotation_axis"].is_array() &&
(j["rotation_axis"].size() == 3)) {
for (int i = 0; i < 3; i++)
message.rotation_axis[i] = j["rotation_axis"][i];
}
if (j.contains("space_group_number"))
message.space_group_number = j["space_group_number"];
if (j.contains("roi"))
@@ -857,6 +910,8 @@ namespace {
ProcessAxis(value, message.detector_translation);
else if (key == "goniometer")
ProcessGoniometerMap(message, value);
else if (key == "grid_scan")
message.grid_scan = ProcessGridScan(value);
else if (key == "pixel_mask_enabled")
message.pixel_mask_enabled = GetCBORBool(value);
else if (key == "jungfrau_conversion_enabled")
@@ -926,7 +981,7 @@ namespace {
auto key = GetCBORString(value);
try {
if (key == "data") {
ProcessImageData(value, message);
message = ProcessImageData(value);
} else {
if (cbor_value_is_tag(&value))
cbor_value_advance(&value);