Merge branch '2404-preview-functionality' into 'main'

Improve preview functionality

See merge request jungfraujoch/nextgendcu!41
This commit is contained in:
2024-04-10 11:17:36 +02:00
25 changed files with 303 additions and 375 deletions
+12 -22
View File
@@ -19,7 +19,6 @@ inline SpotFindingSettings Convert(const org::openapitools::server::model::Spot_
ret.max_pix_per_spot = input.getMaxPixPerSpot();
ret.high_resolution_limit = input.getHighResolutionLimit();
ret.low_resolution_limit = input.getLowResolutionLimit();
ret.preview_indexed_only = input.isPreviewIndexedOnly();
ret.enable = input.isEnable();
return ret;
}
@@ -32,7 +31,6 @@ inline org::openapitools::server::model::Spot_finding_settings Convert(const Spo
ret.setMaxPixPerSpot(input.max_pix_per_spot);
ret.setHighResolutionLimit(input.high_resolution_limit);
ret.setLowResolutionLimit(input.low_resolution_limit);
ret.setPreviewIndexedOnly(input.preview_indexed_only);
ret.setEnable(input.enable);
return ret;
}
@@ -320,15 +318,7 @@ inline PreviewJPEGSettings Convert(const org::openapitools::server::model::Previ
ret.jpeg_quality = input.getJpegQuality();
ret.saturation_value = input.getSaturation();
ret.show_roi = input.isShowRoi();
return ret;
}
inline org::openapitools::server::model::Preview_settings Convert(const PreviewJPEGSettings& settings) {
org::openapitools::server::model::Preview_settings ret{};
ret.setJpegQuality(settings.jpeg_quality);
ret.setSaturation(settings.saturation_value);
ret.setShowSpots(settings.show_spots);
ret.setShowRoi(settings.show_roi);
ret.show_indexed = input.isShowIndexed();
return ret;
}
@@ -712,8 +702,18 @@ void JFJochBrokerHttp::preview_calibration_tiff_get(Pistache::Http::ResponseWrit
response.send(Pistache::Http::Code::Not_Found);
}
void
JFJochBrokerHttp::preview_image_jpeg_post(const org::openapitools::server::model::Preview_settings &previewSettings,
Pistache::Http::ResponseWriter &response) {
std::string s = state_machine.GetPreviewJPEG(Convert(previewSettings));
if (!s.empty())
response.send(Pistache::Http::Code::Ok, s, Pistache::Http::Mime::MediaType::fromString("image/jpeg"));
else
response.send(Pistache::Http::Code::Not_Found);
}
void JFJochBrokerHttp::preview_image_jpeg_get(Pistache::Http::ResponseWriter &response) {
std::string s = state_machine.GetPreviewJPEG();
std::string s = state_machine.GetPreviewJPEG(PreviewJPEGSettings());
if (!s.empty())
response.send(Pistache::Http::Code::Ok, s, Pistache::Http::Mime::MediaType::fromString("image/jpeg"));
else
@@ -728,16 +728,6 @@ void JFJochBrokerHttp::preview_image_tiff_get(Pistache::Http::ResponseWriter &re
response.send(Pistache::Http::Code::Not_Found);
}
void JFJochBrokerHttp::preview_jpeg_settings_get(Pistache::Http::ResponseWriter &response) {
ProcessOutput(Convert(state_machine.GetPreviewJPEGSettings()), response);
}
void JFJochBrokerHttp::preview_jpeg_settings_put(const org::openapitools::server::model::Preview_settings &previewSettings,
Pistache::Http::ResponseWriter &response) {
state_machine.SetPreviewJPEGSettings(Convert(previewSettings));
response.send(Pistache::Http::Code::Ok);
}
void JFJochBrokerHttp::plot_resolution_estimate_histogram_get(Pistache::Http::ResponseWriter &response) {
PlotRequest req{.type = PlotType::ResEstimation, .binning = 0};
auto plot = state_machine.GetPlots(req);
+2 -6
View File
@@ -100,14 +100,10 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void preview_calibration_tiff_get(Pistache::Http::ResponseWriter &response) override;
void preview_image_jpeg_get(Pistache::Http::ResponseWriter &response) override;
void preview_image_jpeg_post(const org::openapitools::server::model::Preview_settings &previewSettings,
Pistache::Http::ResponseWriter &response) override;
void preview_image_tiff_get(Pistache::Http::ResponseWriter &response) override;
void preview_jpeg_settings_get(Pistache::Http::ResponseWriter &response) override;
void preview_jpeg_settings_put(const org::openapitools::server::model::Preview_settings &previewSettings,
Pistache::Http::ResponseWriter &response) override;
void roi_box_get(Pistache::Http::ResponseWriter &response) override;
void roi_box_put(const org::openapitools::server::model::Roi_box_list &roiBoxList,
Pistache::Http::ResponseWriter &response) override;
+2 -10
View File
@@ -653,16 +653,8 @@ std::optional<std::string> JFJochStateMachine::CheckError() {
return {};
}
void JFJochStateMachine::SetPreviewJPEGSettings(const PreviewJPEGSettings &settings) {
preview_jpeg_settings = settings;
}
PreviewJPEGSettings JFJochStateMachine::GetPreviewJPEGSettings() const {
return preview_jpeg_settings;
}
std::string JFJochStateMachine::GetPreviewJPEG() const {
return services.GetPreviewJPEG(preview_jpeg_settings);
std::string JFJochStateMachine::GetPreviewJPEG(const PreviewJPEGSettings& settings) const {
return services.GetPreviewJPEG(settings);
}
std::string JFJochStateMachine::GetPreviewTIFF(bool calibration) const {
+1 -9
View File
@@ -74,7 +74,6 @@ struct DetectorSettings {
std::optional<int64_t> internal_packet_generator_images;
};
struct RadialIntegrationSettings {
bool solid_angle_correction;
std::optional<float> polarization_factor;
@@ -113,11 +112,6 @@ class JFJochStateMachine {
mutable std::mutex data_processing_settings_mutex;
SpotFindingSettings data_processing_settings;
// Not protected with mutex:
// little harm of having preview image out-of-sync, given these images are regularly recalculated
// while there is risk of deadlock with too many mutexes
PreviewJPEGSettings preview_jpeg_settings;
// Private functions assume that lock m is acquired
void MeasurementThread();
void PedestalThread(std::unique_lock<std::mutex> ul);
@@ -169,9 +163,7 @@ public:
void SetRadialIntegrationSettings(const RadialIntegrationSettings& settings);
RadialIntegrationSettings GetRadialIntegrationSettings() const;
void SetPreviewJPEGSettings(const PreviewJPEGSettings& settings);
PreviewJPEGSettings GetPreviewJPEGSettings() const;
std::string GetPreviewJPEG() const;
std::string GetPreviewJPEG(const PreviewJPEGSettings& settings) const;
std::string GetPreviewTIFF(bool calibration) const;
void LoadInternalGeneratorImage(const void *data, size_t size, uint64_t image_number);
+23 -44
View File
@@ -63,9 +63,8 @@ void DefaultApi::setupRoutes() {
Routes::Post(*router, base + "/plot/strong_pixel", Routes::bind(&DefaultApi::plot_strong_pixel_post_handler, this));
Routes::Get(*router, base + "/preview/calibration.tiff", Routes::bind(&DefaultApi::preview_calibration_tiff_get_handler, this));
Routes::Get(*router, base + "/preview/image.jpeg", Routes::bind(&DefaultApi::preview_image_jpeg_get_handler, this));
Routes::Post(*router, base + "/preview/image.jpeg", Routes::bind(&DefaultApi::preview_image_jpeg_post_handler, this));
Routes::Get(*router, base + "/preview/image.tiff", Routes::bind(&DefaultApi::preview_image_tiff_get_handler, this));
Routes::Get(*router, base + "/preview/jpeg_settings", Routes::bind(&DefaultApi::preview_jpeg_settings_get_handler, this));
Routes::Put(*router, base + "/preview/jpeg_settings", Routes::bind(&DefaultApi::preview_jpeg_settings_put_handler, this));
Routes::Get(*router, base + "/roi/box", Routes::bind(&DefaultApi::roi_box_get_handler, this));
Routes::Put(*router, base + "/roi/box", Routes::bind(&DefaultApi::roi_box_put_handler, this));
Routes::Get(*router, base + "/roi/circle", Routes::bind(&DefaultApi::roi_circle_get_handler, this));
@@ -882,47 +881,7 @@ void DefaultApi::preview_image_jpeg_get_handler(const Pistache::Rest::Request &,
}
}
void DefaultApi::preview_image_tiff_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
try {
try {
this->preview_image_tiff_get(response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::preview_jpeg_settings_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
try {
try {
this->preview_jpeg_settings_get(response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::preview_jpeg_settings_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
void DefaultApi::preview_image_jpeg_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
@@ -940,7 +899,27 @@ void DefaultApi::preview_jpeg_settings_put_handler(const Pistache::Rest::Request
}
try {
this->preview_jpeg_settings_put(previewSettings, response);
this->preview_image_jpeg_post(previewSettings, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
void DefaultApi::preview_image_tiff_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
try {
try {
this->preview_image_tiff_get(response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
+10 -18
View File
@@ -88,9 +88,8 @@ private:
void plot_strong_pixel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_calibration_tiff_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_image_jpeg_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_image_jpeg_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_image_tiff_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_jpeg_settings_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void preview_jpeg_settings_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void roi_box_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void roi_box_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void roi_circle_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
@@ -339,13 +338,21 @@ private:
/// </remarks>
virtual void preview_calibration_tiff_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get last preview image in JPEG format
/// Get last preview image in JPEG format using default settings
/// </summary>
/// <remarks>
///
/// </remarks>
virtual void preview_image_jpeg_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get last preview image in JPEG format using custom settings
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="previewSettings"> (optional)</param>
virtual void preview_image_jpeg_post(const org::openapitools::server::model::Preview_settings &previewSettings, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get last preview image in TIFF format
/// </summary>
/// <remarks>
@@ -353,21 +360,6 @@ private:
/// </remarks>
virtual void preview_image_tiff_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get JPEG rendering configuration
/// </summary>
/// <remarks>
/// Can be done anytime
/// </remarks>
virtual void preview_jpeg_settings_get(Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Configure JPEG rendering of preview images
/// </summary>
/// <remarks>
/// Can be done at any state of the detector
/// </remarks>
/// <param name="previewSettings"> (optional)</param>
virtual void preview_jpeg_settings_put(const org::openapitools::server::model::Preview_settings &previewSettings, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Get box ROIs
/// </summary>
/// <remarks>
+31 -2
View File
@@ -28,6 +28,8 @@ Preview_settings::Preview_settings()
m_Show_roiIsSet = false;
m_Jpeg_quality = 0L;
m_Jpeg_qualityIsSet = false;
m_Show_indexed = false;
m_Show_indexedIsSet = false;
}
@@ -88,7 +90,7 @@ bool Preview_settings::validate(std::stringstream& msg, const std::string& pathP
}
}
return success;
}
@@ -107,7 +109,10 @@ bool Preview_settings::operator==(const Preview_settings& rhs) const
((!showRoiIsSet() && !rhs.showRoiIsSet()) || (showRoiIsSet() && rhs.showRoiIsSet() && isShowRoi() == rhs.isShowRoi())) &&
((!jpegQualityIsSet() && !rhs.jpegQualityIsSet()) || (jpegQualityIsSet() && rhs.jpegQualityIsSet() && getJpegQuality() == rhs.getJpegQuality()))
((!jpegQualityIsSet() && !rhs.jpegQualityIsSet()) || (jpegQualityIsSet() && rhs.jpegQualityIsSet() && getJpegQuality() == rhs.getJpegQuality())) &&
((!showIndexedIsSet() && !rhs.showIndexedIsSet()) || (showIndexedIsSet() && rhs.showIndexedIsSet() && isShowIndexed() == rhs.isShowIndexed()))
;
}
@@ -127,6 +132,8 @@ void to_json(nlohmann::json& j, const Preview_settings& o)
j["show_roi"] = o.m_Show_roi;
if(o.jpegQualityIsSet())
j["jpeg_quality"] = o.m_Jpeg_quality;
if(o.showIndexedIsSet())
j["show_indexed"] = o.m_Show_indexed;
}
@@ -148,6 +155,11 @@ void from_json(const nlohmann::json& j, Preview_settings& o)
j.at("jpeg_quality").get_to(o.m_Jpeg_quality);
o.m_Jpeg_qualityIsSet = true;
}
if(j.find("show_indexed") != j.end())
{
j.at("show_indexed").get_to(o.m_Show_indexed);
o.m_Show_indexedIsSet = true;
}
}
@@ -210,6 +222,23 @@ void Preview_settings::unsetJpeg_quality()
{
m_Jpeg_qualityIsSet = false;
}
bool Preview_settings::isShowIndexed() const
{
return m_Show_indexed;
}
void Preview_settings::setShowIndexed(bool const value)
{
m_Show_indexed = value;
m_Show_indexedIsSet = true;
}
bool Preview_settings::showIndexedIsSet() const
{
return m_Show_indexedIsSet;
}
void Preview_settings::unsetShow_indexed()
{
m_Show_indexedIsSet = false;
}
} // namespace org::openapitools::server::model
+9
View File
@@ -83,6 +83,13 @@ public:
void setJpegQuality(int64_t const value);
bool jpegQualityIsSet() const;
void unsetJpeg_quality();
/// <summary>
/// Preview indexed images only
/// </summary>
bool isShowIndexed() const;
void setShowIndexed(bool const value);
bool showIndexedIsSet() const;
void unsetShow_indexed();
friend void to_json(nlohmann::json& j, const Preview_settings& o);
friend void from_json(const nlohmann::json& j, Preview_settings& o);
@@ -95,6 +102,8 @@ protected:
bool m_Show_roiIsSet;
int64_t m_Jpeg_quality;
bool m_Jpeg_qualityIsSet;
bool m_Show_indexed;
bool m_Show_indexedIsSet;
};
+1 -30
View File
@@ -28,8 +28,6 @@ Spot_finding_settings::Spot_finding_settings()
m_Max_pix_per_spot = 0L;
m_High_resolution_limit = 0.0f;
m_Low_resolution_limit = 0.0f;
m_Preview_indexed_only = false;
m_Preview_indexed_onlyIsSet = false;
}
@@ -108,7 +106,7 @@ bool Spot_finding_settings::validate(std::stringstream& msg, const std::string&
}
}
return success;
}
@@ -136,11 +134,8 @@ bool Spot_finding_settings::operator==(const Spot_finding_settings& rhs) const
&&
(getLowResolutionLimit() == rhs.getLowResolutionLimit())
&&
((!previewIndexedOnlyIsSet() && !rhs.previewIndexedOnlyIsSet()) || (previewIndexedOnlyIsSet() && rhs.previewIndexedOnlyIsSet() && isPreviewIndexedOnly() == rhs.isPreviewIndexedOnly()))
;
}
@@ -159,8 +154,6 @@ void to_json(nlohmann::json& j, const Spot_finding_settings& o)
j["max_pix_per_spot"] = o.m_Max_pix_per_spot;
j["high_resolution_limit"] = o.m_High_resolution_limit;
j["low_resolution_limit"] = o.m_Low_resolution_limit;
if(o.previewIndexedOnlyIsSet())
j["preview_indexed_only"] = o.m_Preview_indexed_only;
}
@@ -173,11 +166,6 @@ void from_json(const nlohmann::json& j, Spot_finding_settings& o)
j.at("max_pix_per_spot").get_to(o.m_Max_pix_per_spot);
j.at("high_resolution_limit").get_to(o.m_High_resolution_limit);
j.at("low_resolution_limit").get_to(o.m_Low_resolution_limit);
if(j.find("preview_indexed_only") != j.end())
{
j.at("preview_indexed_only").get_to(o.m_Preview_indexed_only);
o.m_Preview_indexed_onlyIsSet = true;
}
}
@@ -237,23 +225,6 @@ void Spot_finding_settings::setLowResolutionLimit(float const value)
{
m_Low_resolution_limit = value;
}
bool Spot_finding_settings::isPreviewIndexedOnly() const
{
return m_Preview_indexed_only;
}
void Spot_finding_settings::setPreviewIndexedOnly(bool const value)
{
m_Preview_indexed_only = value;
m_Preview_indexed_onlyIsSet = true;
}
bool Spot_finding_settings::previewIndexedOnlyIsSet() const
{
return m_Preview_indexed_onlyIsSet;
}
void Spot_finding_settings::unsetPreview_indexed_only()
{
m_Preview_indexed_onlyIsSet = false;
}
} // namespace org::openapitools::server::model
-9
View File
@@ -92,13 +92,6 @@ public:
/// </summary>
float getLowResolutionLimit() const;
void setLowResolutionLimit(float const value);
/// <summary>
///
/// </summary>
bool isPreviewIndexedOnly() const;
void setPreviewIndexedOnly(bool const value);
bool previewIndexedOnlyIsSet() const;
void unsetPreview_indexed_only();
friend void to_json(nlohmann::json& j, const Spot_finding_settings& o);
friend void from_json(const nlohmann::json& j, Spot_finding_settings& o);
@@ -117,8 +110,6 @@ protected:
float m_Low_resolution_limit;
bool m_Preview_indexed_only;
bool m_Preview_indexed_onlyIsSet;
};
+17 -22
View File
@@ -344,9 +344,6 @@ components:
low_resolution_limit:
type: number
format: float
preview_indexed_only:
type: boolean
default: false
rad_int_settings:
type: object
required:
@@ -598,6 +595,9 @@ components:
format: int64
minimum: 0
maximum: 100
show_indexed:
type: boolean
description: "Preview indexed images only"
error_message:
type: object
@@ -1429,8 +1429,8 @@ paths:
schema:
$ref: '#/components/schemas/calibration_statistics'
/preview/image.jpeg:
get:
summary: Get last preview image in JPEG format
post:
summary: Get last preview image in JPEG format using custom settings
responses:
"200":
description: Preview image
@@ -1441,18 +1441,6 @@ paths:
format: binary
"404":
description: No preview image recorded so far
/preview/jpeg_settings:
put:
summary: Configure JPEG rendering of preview images
description: Can be done at any state of the detector
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/preview_settings'
responses:
"200":
description: Everything OK
"400":
description: Input parsing or validation error
content:
@@ -1466,16 +1454,23 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/error_message'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/preview_settings'
get:
summary: Get JPEG rendering configuration
description: Can be done anytime
summary: Get last preview image in JPEG format using default settings
responses:
"200":
description: Everything OK
description: Preview image
content:
application/json:
image/jpeg:
schema:
$ref: '#/components/schemas/preview_settings'
type: string
format: binary
"404":
description: No preview image recorded so far
/preview/image.tiff:
get:
summary: Get last preview image in TIFF format
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4,7 +4,7 @@
#include "JFJochException.h"
ROIMask::ROIMask(int64_t in_xpixel, int64_t in_ypixel)
: mask(in_xpixel * in_ypixel, 0),
: mask(in_xpixel * in_ypixel, UINT16_MAX),
xpixel(in_xpixel), ypixel(in_ypixel) {
}
+1
View File
@@ -13,6 +13,7 @@ struct PreviewJPEGSettings {
int64_t jpeg_quality = 70;
bool show_spots = true;
bool show_roi = false;
bool show_indexed = false;
};
class PreviewImage {
+1 -5
View File
@@ -14,7 +14,6 @@ import MeasurementStatistics from "./components/MeasurementStatistics";
import DetectorStatus from "./components/DetectorStatus";
import Paper from "@mui/material/Paper";
import PreviewImage from "./components/PreviewImage";
import PreviewImageSettings from "./components/PreviewImageSettings";
import ROI from "./components/ROI";
const jfjoch_theme = createTheme({
@@ -106,12 +105,9 @@ class App extends Component<MyProps, MyState> {
{
this.renderTitleWithSwitch("Live image preview", this.state.show_preview, this.showPreviewToggle)
}
<Grid item xs={9}>
<Grid item xs={12}>
{this.state.show_preview ? <PreviewImage/> : ""}
</Grid>
<Grid item xs={3}>
{this.state.show_preview ? <PreviewImageSettings/> : ""}
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("JUNGFRAU module calibration",
@@ -21,8 +21,7 @@ class DataProcessingSettings extends Component<MyProps, MyState> {
min_pix_per_spot: 2,
max_pix_per_spot: 50,
high_resolution_limit: 2.5,
low_resolution_limit: 20.0,
preview_indexed_only: false
low_resolution_limit: 20.0
},
connection_error: true
}
@@ -107,15 +106,6 @@ class DataProcessingSettings extends Component<MyProps, MyState> {
enableSpotFindingToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.enable = event.target.checked;
if (!x.s.enable)
x.s.preview_indexed_only = false;
this.putValues2(x);
this.getValues();
}
previewIndexedToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.preview_indexed_only = event.target.checked;
this.putValues2(x);
this.getValues();
}
@@ -152,10 +142,7 @@ class DataProcessingSettings extends Component<MyProps, MyState> {
value={Number(this.state.s.high_resolution_limit)}
onChange={this.setHighResolutionLimit}
min={1} max={5} step={0.2} valueLabelDisplay="auto" />
<br/>
<Switch onChange={this.previewIndexedToggle} checked={this.state.s.preview_indexed_only}
disabled={this.state.connection_error || !this.state.s.enable}/>
Preview only indexed frames <br/><br/>
<br/><br/>
</Grid>
<Grid item xs={1}/>
+119 -20
View File
@@ -1,14 +1,17 @@
import React, {Component} from 'react';
import Paper from "@mui/material/Paper";
import {Box, Slider, Stack, Switch} from "@mui/material";
import {TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import {preview_settings} from "../openapi";
import {handleErrors} from "./handleErrors";
import {Stack} from "@mui/material";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
type MyProps = {}
type MyState = {
settings: preview_settings,
s: Blob | null,
s_url: string | null,
update: boolean,
connection_error: boolean
}
class PreviewImage extends Component<MyProps, MyState> {
@@ -16,18 +19,82 @@ class PreviewImage extends Component<MyProps, MyState> {
state : MyState = {
s: null,
s_url: null,
settings: {
saturation: 10,
jpeg_quality: 95,
show_spots: true,
show_roi: false,
show_indexed: false
},
s_url: "",
update: true,
connection_error: true
}
updateToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({
update: event.target.checked
});
}
setSaturation = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
settings : {
...prevState.settings,
saturation: newValue as number
}
}
));
}
showSpotsToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState(prevState => (
{
settings : {
...prevState.settings,
show_spots: event.target.checked
}
})
);
}
showROIToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState(prevState => (
{
settings : {
...prevState.settings,
show_roi: event.target.checked
}
})
);
}
showIndexedToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState(prevState => (
{
settings : {
...prevState.settings,
show_indexed: event.target.checked
}
})
);
}
getValues() {
fetch("/preview/image.jpeg")
if (!this.state.update)
return;
fetch("/preview/image.jpeg", {
method: "POST",
body: JSON.stringify(this.state.settings)
})
.then(handleErrors)
.then(data => data.blob())
.then(data => {
const url = URL.createObjectURL(data);
this.setState({s: data, s_url: url, connection_error: false});
}).catch(error => {
console.log(error);
this.setState({connection_error: true});
})
}
@@ -41,22 +108,54 @@ class PreviewImage extends Component<MyProps, MyState> {
clearInterval(this.interval);
}
preview() {
return <div><br/>
<Stack spacing={2} direction="row" sx={{ mb: 1 }} alignItems="center">
&nbsp;&nbsp;<strong>Preview image</strong>
<Switch disabled={this.state.connection_error} checked={this.state.update}
onChange={this.updateToggle} name="Update"/>
Update&nbsp;&nbsp;&nbsp;
<Switch disabled={this.state.connection_error} checked={this.state.settings.show_spots}
onChange={this.showSpotsToggle} name="Show spots"/>
Show spots&nbsp;&nbsp;&nbsp;
<Switch disabled={this.state.connection_error} checked={this.state.settings.show_roi}
onChange={this.showROIToggle} name="Show ROI"/>
Show ROI&nbsp;&nbsp;&nbsp;
<Switch disabled={this.state.connection_error} checked={this.state.settings.show_indexed}
onChange={this.showIndexedToggle} name="Show ROI"/>
Show only indexed images&nbsp;&nbsp;&nbsp;
<Box sx={{ width: 200 }}>
<Slider disabled={this.state.connection_error}
value={Number(this.state.settings.saturation)} min={1} max={40}
onChange={this.setSaturation} valueLabelDisplay="auto"/> <br/>Saturation value
</Box>
&nbsp;&nbsp;&nbsp;
</Stack>
<br/>
{
this.state.s_url !== null ?
<Stack
direction="row"
justifyContent="center"
alignItems="center"
>
<TransformWrapper>
<TransformComponent>
<img src={this.state.s_url} alt="Live preview" style={{maxWidth: "100%", maxHeight: 900}}/>
</TransformComponent>
</TransformWrapper>
</Stack>: <div/>
}
<br/>
</div>
}
render() {
return <Paper style={{alignItems: 'center', textAlign: 'center'}} sx={{ height: '60%', width: '100%', m: 2}}
component={Stack}
direction="column" justifyContent="center">
{(!this.state.connection_error && (this.state.s_url !== null)) ?
<div>
<br/>
<TransformWrapper>
<TransformComponent>
<img src={this.state.s_url} alt="Live preview" style={{maxWidth: "90%", maxHeight: "90%"}}/>
</TransformComponent>
</TransformWrapper>
<br/>
</div>
: "Preview not available"}
</Paper>;
return <Paper sx={{height: 1050, width: 850, m: 2}}
component={Stack}
direction="column">
{(!this.state.connection_error && (this.state.s_url !== null)) ? this.preview() : "Preview not available"}
</Paper>
}
}
@@ -1,101 +0,0 @@
import React, {Component} from 'react';
import {Grid, Slider, Switch, Typography} from "@mui/material";
import {DefaultService, preview_settings} from "../openapi";
import Paper from "@mui/material/Paper";
type MyProps = {}
type MyState = {
s: preview_settings,
connection_error: boolean
}
class PreviewImageSettings extends Component<MyProps, MyState> {
interval : NodeJS.Timer | undefined;
state : MyState = {
s: {
saturation: 10,
jpeg_quality: 95,
show_spots: false,
show_roi: false
},
connection_error: true
}
getValues() {
DefaultService.getPreviewJpegSettings()
.then(data => this.setState({s: data, connection_error: false}))
.catch(error => {
this.setState({connection_error: true});
});
}
componentDidMount() {
this.getValues();
this.interval = setInterval(() => this.getValues(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
putValues() {
DefaultService.putPreviewJpegSettings(this.state.s)
.catch(error => console.log(error) );
}
putValues2(x: MyState) {
DefaultService.putPreviewJpegSettings(x.s)
.catch(error => console.log(error) );
}
setSaturation = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
saturation: newValue as number
}
}
));
this.putValues();
}
showSpotsToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.show_spots = event.target.checked;
this.putValues2(x);
}
showROIToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.show_roi = event.target.checked;
this.putValues2(x);
}
render() {
return <Paper style={{textAlign: 'center'}} sx={{ height: '60%', width: '100%' }}>
<Grid container spacing={0}>
<Grid item xs={1}/>
<Grid item xs={10}>
<br/>
<strong>Preview settings</strong><br/><br/><br/>
<Typography gutterBottom> Image saturation value </Typography>
<Slider disabled={this.state.connection_error}
value={Number(this.state.s.saturation)} min={1} max={80}
onChange={this.setSaturation} valueLabelDisplay="auto"/><br/>
<Switch disabled={this.state.connection_error} checked={this.state.s.show_spots}
onChange={this.showSpotsToggle} name="Show spots"/> Show spots<br/>
<Switch disabled={this.state.connection_error} checked={this.state.s.show_roi}
onChange={this.showROIToggle} name="Show ROI"/> Show ROI<br/>
</Grid>
<Grid item xs={1}/>
</Grid>
<br/><br/>
</Paper>;
}
}
export default PreviewImageSettings;
@@ -23,5 +23,9 @@ export type preview_settings = {
* Quality of JPEG image (100 - highest; 0 - lowest)
*/
jpeg_quality?: number;
/**
* Preview indexed images only
*/
show_indexed?: boolean;
};
@@ -11,6 +11,5 @@ export type spot_finding_settings = {
max_pix_per_spot: number;
high_resolution_limit: number;
low_resolution_limit: number;
preview_indexed_only?: boolean;
};
@@ -762,7 +762,29 @@ export class DefaultService {
}
/**
* Get last preview image in JPEG format
* Get last preview image in JPEG format using custom settings
* @param requestBody
* @returns binary Preview image
* @throws ApiError
*/
public static postPreviewImageJpeg(
requestBody?: preview_settings,
): CancelablePromise<Blob> {
return __request(OpenAPI, {
method: 'POST',
url: '/preview/image.jpeg',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Input parsing or validation error`,
404: `No preview image recorded so far`,
500: `Error within Jungfraujoch code - see output message.`,
},
});
}
/**
* Get last preview image in JPEG format using default settings
* @returns binary Preview image
* @throws ApiError
*/
@@ -776,41 +798,6 @@ export class DefaultService {
});
}
/**
* Configure JPEG rendering of preview images
* Can be done at any state of the detector
* @param requestBody
* @returns any Everything OK
* @throws ApiError
*/
public static putPreviewJpegSettings(
requestBody?: preview_settings,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/preview/jpeg_settings',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Input parsing or validation error`,
500: `Error within Jungfraujoch code - see output message.`,
},
});
}
/**
* Get JPEG rendering configuration
* Can be done anytime
* @returns preview_settings Everything OK
* @throws ApiError
*/
public static getPreviewJpegSettings(): CancelablePromise<preview_settings> {
return __request(OpenAPI, {
method: 'GET',
url: '/preview/jpeg_settings',
});
}
/**
* Get last preview image in TIFF format
* @returns binary Preview image
-1
View File
@@ -13,7 +13,6 @@ struct SpotFindingSettings {
int64_t max_pix_per_spot = 50; // Maximum pixels per spot
float high_resolution_limit = 2.5;
float low_resolution_limit = 50.0;
bool preview_indexed_only = false;
};
#endif //JUNGFRAUJOCH_SPOTFINDINGSETTINGS_H
+13 -3
View File
@@ -42,8 +42,10 @@ JFJochReceiver::JFJochReceiver(const DiffractionExperiment& in_experiment,
az_int_mapping(experiment),
plots(experiment, az_int_mapping),
preview_counter(experiment.GetPreviewPeriod()),
preview_counter_indexed(experiment.GetPreviewPeriod()),
spot_finding_settings(in_spot_finding_settings),
preview_image(experiment)
preview_image(experiment),
preview_image_indexed(experiment)
{
push_images_to_writer = (experiment.GetImageNum() > 0) && (!experiment.GetFilePrefix().empty());
@@ -362,12 +364,17 @@ void JFJochReceiver::FrameTransformationThread() {
message.image = transformation.GetCompressedImage();
compressed_size += message.image.size;
if (preview_counter.GeneratePreview() && (!local_spot_finding_settings.preview_indexed_only || indexed)) {
if (preview_counter.GeneratePreview()) {
preview_image.UpdateImage(transformation.GetImage(), message.spots);
if (preview_publisher)
preview_publisher->SendImage(message);
}
if (indexed) {
if (preview_counter_indexed.GeneratePreview())
preview_image_indexed.UpdateImage(transformation.GetImage(), message.spots);
}
if (push_images_to_writer) {
if (image_pusher.SendImage(message)) {
images_sent++; // Handle case when image not sent properly
@@ -583,7 +590,10 @@ std::string JFJochReceiver::GetTIFF(bool calibration_run) const {
}
std::string JFJochReceiver::GetJPEG(const PreviewJPEGSettings &settings) const {
return preview_image.GenerateJPEG(settings);
if (settings.show_indexed)
return preview_image_indexed.GenerateJPEG(settings);
else
return preview_image.GenerateJPEG(settings);
}
void JFJochReceiver::GetXFELEventCode(std::vector<uint64_t> &v) const {
+3
View File
@@ -111,6 +111,9 @@ class JFJochReceiver {
PreviewCounter preview_counter;
PreviewImage preview_image;
PreviewCounter preview_counter_indexed;
PreviewImage preview_image_indexed;
void AcquireThread(uint16_t data_stream);
void FrameTransformationThread();
void Cancel(const JFJochException &e);
+10
View File
@@ -89,3 +89,13 @@ TEST_CASE("ROIMask") {
REQUIRE(it2->second == 1);
REQUIRE(mask.GetMask()[405 * x.GetXPixelsNum()+300] == 1);
}
TEST_CASE("ROIMask_Empty") {
DiffractionExperiment x(DetectorGeometry(1));
size_t err = 0;
for (const auto &i: x.ROI().GetMask()) {
if (i != UINT16_MAX)
err++;
}
REQUIRE(err == 0);
}