jfjoch_broker: Add auto-contrast option
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m23s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m3s
Build Packages / Generate python client (push) Successful in 32s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m43s
Build Packages / Build documentation (push) Successful in 37s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8) (push) Successful in 13m13s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m35s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m29s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m42s
Build Packages / build:rpm (rocky9) (push) Successful in 14m6s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m39s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 11m2s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 11m53s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 12m4s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 11m34s
Build Packages / Generate python client (pull_request) Successful in 14s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 12m18s
Build Packages / Create release (pull_request) Has been skipped
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 12m55s
Build Packages / Build documentation (pull_request) Successful in 35s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 10m16s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 7m39s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 8m28s
Build Packages / Unit tests (push) Has been cancelled
Build Packages / Unit tests (pull_request) Failing after 1h35m36s

This commit is contained in:
2025-11-28 11:36:31 +01:00
parent 338bbc9519
commit 8210a08454
15 changed files with 105 additions and 31 deletions
+3 -1
View File
@@ -478,6 +478,7 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
const std::optional<int64_t> &jpegQuality,
const std::optional<float> &showResRing,
const std::optional<std::string> &color,
const std::optional<bool> &showResEst,
Pistache::Http::ResponseWriter &response) {
int64_t image_id = id.value_or(ImageBuffer::MaxImage);
PreviewImageSettings settings{};
@@ -485,7 +486,8 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
settings.show_user_mask = showUserMask.value_or(true);
settings.show_roi = showRoi.value_or(false);
settings.show_spots = showSpots.value_or(true);
settings.saturation_value = saturation.value_or(10);
settings.saturation_value = saturation;
settings.background_value = 0.0;
settings.jpeg_quality = jpegQuality.value_or(100);
settings.resolution_ring = showResRing;
settings.scale = ConvertColorScale(color);
+2
View File
@@ -147,6 +147,7 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void image_buffer_image_cbor_get(const std::optional<int64_t> &id,
Pistache::Http::ResponseWriter &response) override;
void image_buffer_image_jpeg_get(const std::optional<int64_t> &id,
const std::optional<bool> &showUserMask,
const std::optional<bool> &showRoi,
@@ -156,6 +157,7 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
const std::optional<int64_t> &jpegQuality,
const std::optional<float> &showResRing,
const std::optional<std::string> &color,
const std::optional<bool> &showResEst,
Pistache::Http::ResponseWriter &response) override;
void image_buffer_image_tiff_get(const std::optional<int64_t> &id, Pistache::Http::ResponseWriter &response) override;
+9 -1
View File
@@ -1114,9 +1114,17 @@ void DefaultApi::image_buffer_image_jpeg_get_handler(const Pistache::Rest::Reque
color = valueQuery_instance;
}
}
auto showResEstQuery = request.query().get("show_res_est");
std::optional<bool> showResEst;
if(showResEstQuery.has_value()){
bool valueQuery_instance;
if(fromStringValue(showResEstQuery.value(), valueQuery_instance)){
showResEst = valueQuery_instance;
}
}
try {
this->image_buffer_image_jpeg_get(id, showUserMask, showRoi, showSpots, showBeamCenter, saturation, jpegQuality, showResRing, color, response);
this->image_buffer_image_jpeg_get(id, showUserMask, showRoi, showSpots, showBeamCenter, saturation, jpegQuality, showResRing, color, showResEst, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
+3 -2
View File
@@ -462,11 +462,12 @@ private:
/// <param name="showRoi">Show ROI areas on the image (optional, default to false)</param>
/// <param name="showSpots">Show spot finding results on the image (optional, default to true)</param>
/// <param name="showBeamCenter">Show beam center on the image (optional, default to true)</param>
/// <param name="saturation">Saturation value to set contrast in the preview image (optional, default to 10.0f)</param>
/// <param name="saturation">Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used (optional, default to 0.0f)</param>
/// <param name="jpegQuality">Quality of JPEG image (100 - highest; 0 - lowest) (optional, default to 100L)</param>
/// <param name="showResRing">Show resolution ring, provided in Angstrom (optional, default to 0.1f)</param>
/// <param name="color">Color scale for preview image: 0 - indigo, 1 - viridis, 2 - B/W, 3 - heat (optional, default to &quot;indigo&quot;)</param>
virtual void image_buffer_image_jpeg_get(const std::optional<int64_t> &id, const std::optional<bool> &showUserMask, const std::optional<bool> &showRoi, const std::optional<bool> &showSpots, const std::optional<bool> &showBeamCenter, const std::optional<float> &saturation, const std::optional<int64_t> &jpegQuality, const std::optional<float> &showResRing, const std::optional<std::string> &color, Pistache::Http::ResponseWriter &response) = 0;
/// <param name="showResEst">Show resolution estimation as a ring (optional, default to false)</param>
virtual void image_buffer_image_jpeg_get(const std::optional<int64_t> &id, const std::optional<bool> &showUserMask, const std::optional<bool> &showRoi, const std::optional<bool> &showSpots, const std::optional<bool> &showBeamCenter, const std::optional<float> &saturation, const std::optional<int64_t> &jpegQuality, const std::optional<float> &showResRing, const std::optional<std::string> &color, const std::optional<bool> &showResEst, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get preview image in TIFF format
/// </summary>
+11 -2
View File
@@ -143,16 +143,17 @@ components:
saturation:
in: query
name: saturation
required: false
schema:
type: number
format: float
default: 10
minimum: -32767
maximum: 32767
description: "Saturation value to set contrast in the preview image"
description: "Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used"
background:
in: query
name: background
required: false
schema:
type: number
format: float
@@ -208,6 +209,13 @@ components:
default: 0.1
minimum: 0.1
maximum: 100.0
resolution_estimate:
in: query
name: show_res_est
description: "Show resolution estimation as a ring"
schema:
type: boolean
default: false
color_scale:
in: query
name: color
@@ -3166,6 +3174,7 @@ paths:
- $ref: '#/components/parameters/jpeg_quality'
- $ref: '#/components/parameters/resolution_ring'
- $ref: '#/components/parameters/color_scale'
- $ref: '#/components/parameters/resolution_estimate'
responses:
"200":
description: Preview image
File diff suppressed because one or more lines are too long
+6 -4
View File
@@ -2665,7 +2665,7 @@ No authorization required
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **image_buffer_image_jpeg_get**
> bytearray image_buffer_image_jpeg_get(id=id, show_user_mask=show_user_mask, show_roi=show_roi, show_spots=show_spots, show_beam_center=show_beam_center, saturation=saturation, jpeg_quality=jpeg_quality, show_res_ring=show_res_ring, color=color)
> bytearray image_buffer_image_jpeg_get(id=id, show_user_mask=show_user_mask, show_roi=show_roi, show_spots=show_spots, show_beam_center=show_beam_center, saturation=saturation, jpeg_quality=jpeg_quality, show_res_ring=show_res_ring, color=color, show_res_est=show_res_est)
Get preview image in JPEG format using custom settings
@@ -2693,14 +2693,15 @@ with jfjoch_client.ApiClient(configuration) as api_client:
show_roi = False # bool | Show ROI areas on the image (optional) (default to False)
show_spots = True # bool | Show spot finding results on the image (optional) (default to True)
show_beam_center = True # bool | Show beam center on the image (optional) (default to True)
saturation = 10 # float | Saturation value to set contrast in the preview image (optional) (default to 10)
saturation = 3.4 # float | Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used (optional)
jpeg_quality = 100 # int | Quality of JPEG image (100 - highest; 0 - lowest) (optional) (default to 100)
show_res_ring = 0.1 # float | Show resolution ring, provided in Angstrom (optional) (default to 0.1)
color = indigo # str | Color scale for preview image: 0 - indigo, 1 - viridis, 2 - B/W, 3 - heat (optional) (default to indigo)
show_res_est = False # bool | Show resolution estimation as a ring (optional) (default to False)
try:
# Get preview image in JPEG format using custom settings
api_response = api_instance.image_buffer_image_jpeg_get(id=id, show_user_mask=show_user_mask, show_roi=show_roi, show_spots=show_spots, show_beam_center=show_beam_center, saturation=saturation, jpeg_quality=jpeg_quality, show_res_ring=show_res_ring, color=color)
api_response = api_instance.image_buffer_image_jpeg_get(id=id, show_user_mask=show_user_mask, show_roi=show_roi, show_spots=show_spots, show_beam_center=show_beam_center, saturation=saturation, jpeg_quality=jpeg_quality, show_res_ring=show_res_ring, color=color, show_res_est=show_res_est)
print("The response of DefaultApi->image_buffer_image_jpeg_get:\n")
pprint(api_response)
except Exception as e:
@@ -2719,10 +2720,11 @@ Name | Type | Description | Notes
**show_roi** | **bool**| Show ROI areas on the image | [optional] [default to False]
**show_spots** | **bool**| Show spot finding results on the image | [optional] [default to True]
**show_beam_center** | **bool**| Show beam center on the image | [optional] [default to True]
**saturation** | **float**| Saturation value to set contrast in the preview image | [optional] [default to 10]
**saturation** | **float**| Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used | [optional]
**jpeg_quality** | **int**| Quality of JPEG image (100 - highest; 0 - lowest) | [optional] [default to 100]
**show_res_ring** | **float**| Show resolution ring, provided in Angstrom | [optional] [default to 0.1]
**color** | **str**| Color scale for preview image: 0 - indigo, 1 - viridis, 2 - B/W, 3 - heat | [optional] [default to indigo]
**show_res_est** | **bool**| Show resolution estimation as a ring | [optional] [default to False]
### Return type
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "jungfraujoch-frontend",
"version": "1.0.0-rc.109",
"version": "1.0.0-rc.110",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "jungfraujoch-frontend",
"version": "1.0.0-rc.109",
"version": "1.0.0-rc.110",
"license": "GPL-3.0",
"dependencies": {
"@emotion/react": "^11.10.4",
+1
View File
@@ -54,6 +54,7 @@ export type { plot } from './models/plot';
export { plot_type } from './models/plot_type';
export { plot_unit_x } from './models/plot_unit_x';
export type { plots } from './models/plots';
export type { resolution_estimate } from './models/resolution_estimate';
export type { resolution_ring } from './models/resolution_ring';
export type { roi } from './models/roi';
export type { roi_azim_list } from './models/roi_azim_list';
@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Show resolution estimation as a ring
*/
export type resolution_estimate = boolean;
+1 -1
View File
@@ -4,6 +4,6 @@
/* eslint-disable */
/**
* Saturation value to set contrast in the preview image
* Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used
*/
export type saturation = number;
@@ -1078,10 +1078,11 @@ export class DefaultService {
* @param showRoi Show ROI areas on the image
* @param showSpots Show spot finding results on the image
* @param showBeamCenter Show beam center on the image
* @param saturation Saturation value to set contrast in the preview image
* @param saturation Saturation value to set contrast in the preview image; if not provided, then autocontrast procedure is used
* @param jpegQuality Quality of JPEG image (100 - highest; 0 - lowest)
* @param showResRing Show resolution ring, provided in Angstrom
* @param color Color scale for preview image: 0 - indigo, 1 - viridis, 2 - B/W, 3 - heat
* @param showResEst Show resolution estimation as a ring
* @returns binary Preview image
* @throws ApiError
*/
@@ -1091,10 +1092,11 @@ export class DefaultService {
showRoi: boolean = false,
showSpots: boolean = true,
showBeamCenter: boolean = true,
saturation: number = 10,
saturation?: number,
jpegQuality: number = 100,
showResRing: number = 0.1,
color: 'indigo' | 'viridis' | 'bw' | 'heat' = 'indigo',
showResEst: boolean = false,
): CancelablePromise<Blob> {
return __request(OpenAPI, {
method: 'GET',
@@ -1109,6 +1111,7 @@ export class DefaultService {
'jpeg_quality': jpegQuality,
'show_res_ring': showResRing,
'color': color,
'show_res_est': showResEst,
},
errors: {
400: `Input parsing or validation error`,
+42 -10
View File
@@ -48,14 +48,46 @@ void PreviewImage::roi(std::vector<rgb> &ret, int64_t in_xpixel, int64_t in_ypix
}
template<class T>
std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t* value_8,
std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t *value_8,
int64_t special_value_64,
int64_t sat_value_64,
const ColorScale &scale,
const PreviewImageSettings& settings) const {
const PreviewImageSettings &settings) const {
auto value = reinterpret_cast<const T *>(value_8);
auto special_value = static_cast<T>(special_value_64);
std::vector<rgb> ret(xpixel*ypixel);
float background = settings.background_value.value_or(0.0);
float foreground;
if (settings.saturation_value.has_value())
foreground = settings.saturation_value.value();
else {
// Auto-contrast procedure
std::vector<int64_t> valid;
valid.reserve(xpixel * ypixel);
for (int i = 0; i < xpixel * ypixel; i++) {
if ((value[i] != special_value)
&& (value[i] != sat_value_64)
&& (mask[i] != MaskDet)
&& (mask[i] != MaskGap)
&& (!settings.show_user_mask || (mask[i] != MaskUsr)))
valid.push_back(static_cast<int64_t>(value[i]));
}
if (!valid.empty()) {
const size_t m = valid.size();
size_t ignore = std::max<size_t>(1, static_cast<size_t>(std::floor(m * auto_foreground_range)));
if (ignore >= m) ignore = m - 1; // ensure at least one value remains
const size_t rank = m - ignore - 1; // 0-based index for the desired value
std::nth_element(valid.begin(), valid.begin() + rank, valid.end());
foreground = static_cast<float>(valid[rank]);
} else {
// Fallback to something above background if no valid pixels remain
foreground = background + 1.0f;
}
}
std::vector<rgb> ret(xpixel * ypixel);
for (int i = 0; i < xpixel*ypixel; i++) {
if (mask[i] == MaskGap)
ret[i] = scale.Apply(ColorScaleSpecial::Gap);
@@ -64,7 +96,7 @@ std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t* value_8,
|| (settings.show_user_mask && (mask[i] == MaskUsr))) {
ret[i] = scale.Apply(ColorScaleSpecial::BadPixel);
} else
ret[i] = scale.Apply(value[i], 0.0, settings.saturation_value);;
ret[i] = scale.Apply(value[i], background, foreground);
}
return ret;
}
@@ -214,22 +246,22 @@ std::vector<rgb> PreviewImage::GenerateRGB(const PreviewImageSettings &settings,
switch (msg.image.GetMode()) {
case CompressedImageMode::Int8:
v = GenerateRGB<int8_t>(image_ptr, INT8_MIN, scale, settings);
v = GenerateRGB<int8_t>(image_ptr, INT8_MIN, INT8_MAX, scale, settings);
break;
case CompressedImageMode::Int16:
v = GenerateRGB<int16_t>(image_ptr, INT16_MIN, scale, settings);
v = GenerateRGB<int16_t>(image_ptr, INT16_MIN, INT16_MAX, scale, settings);
break;
case CompressedImageMode::Int32:
v = GenerateRGB<int32_t>(image_ptr, INT32_MIN, scale, settings);
v = GenerateRGB<int32_t>(image_ptr, INT32_MIN, INT32_MAX, scale, settings);
break;
case CompressedImageMode::Uint8:
v = GenerateRGB<uint8_t>(image_ptr,UINT8_MAX, scale, settings);
v = GenerateRGB<uint8_t>(image_ptr,UINT8_MAX, UINT8_MAX, scale, settings);
break;
case CompressedImageMode::Uint16:
v = GenerateRGB<uint16_t>(image_ptr,UINT16_MAX, scale, settings);
v = GenerateRGB<uint16_t>(image_ptr,UINT16_MAX, UINT16_MAX, scale, settings);
break;
case CompressedImageMode::Uint32:
v = GenerateRGB<uint32_t>(image_ptr,UINT16_MAX, scale, settings);
v = GenerateRGB<uint32_t>(image_ptr,UINT32_MAX, UINT32_MAX, scale, settings);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mode not supported");
+5 -1
View File
@@ -16,7 +16,8 @@
enum class PreviewImageFormat {JPEG, TIFF};
struct PreviewImageSettings {
float saturation_value = 10;
std::optional<float> saturation_value = 10;
std::optional<float> background_value = 0;
int64_t jpeg_quality = 70;
bool show_beam_center = true;
bool show_spots = true;
@@ -46,9 +47,12 @@ class PreviewImage {
constexpr static uint8_t MaskUsr = 2;
constexpr static uint8_t MaskDet = 3;
constexpr static float auto_foreground_range = 0.001f;
template<class T>
std::vector<rgb> GenerateRGB(const uint8_t* value,
int64_t special_value,
int64_t sat_value,
const ColorScale &scale,
const PreviewImageSettings& settings) const;
std::vector<rgb> GenerateRGB(const PreviewImageSettings& settings, const DataMessage &msg) const;
-1
View File
@@ -995,7 +995,6 @@ TEST_CASE("JFJochIntegrationTest_ZMQ_lysozyme_spot_and_index_32", "[JFJochReceiv
std::string jpeg;
PreviewImageSettings jpeg_settings{
.saturation_value = 10,
.jpeg_quality = 100,
.show_spots = true
};