Fixes to 8x10g FPGA image and frontend

This commit is contained in:
2024-10-16 09:12:24 +02:00
parent 4cf20ae71b
commit 4ae0668f2f
26 changed files with 839 additions and 294 deletions

View File

@@ -15,7 +15,7 @@ build:x86:gcc:
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j48
@@ -111,7 +111,7 @@ test:x86:gcc:
- gcc
- x86
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
@@ -139,7 +139,7 @@ test:x86:crystfel:
- x86
- crystfel
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
@@ -162,7 +162,7 @@ test:x86:xds_durin:
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
@@ -208,7 +208,7 @@ test:x86:xia2.ssx:
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- mkdir -p dials_test
- cd build

View File

@@ -493,6 +493,12 @@ void JFJochBrokerHttp::statistics_get(const std::optional<bool> &compression, Pi
if (det_status.has_value())
statistics.setDetector(Convert(det_status.value()));
statistics.setDetectorSettings(Convert(state_machine.GetDetectorSettings()));
statistics.setDetectorList(Convert(state_machine.GetDetectorsList()));
statistics.setDataProcessingSettings(Convert(state_machine.GetSpotFindingSettings()));
statistics.setInstrumentMetadata(Convert(state_machine.GetInstrumentMetadata()));
statistics.setImageFormatSettings(Convert(state_machine.GetImageFormatSettings()));
nlohmann::json j = statistics;
if (!compression.has_value() || compression.value())
response.setCompression(Pistache::Http::Header::Encoding::Deflate);

View File

@@ -22,6 +22,11 @@ namespace org::openapitools::server::model
Jfjoch_statistics::Jfjoch_statistics()
{
m_DetectorIsSet = false;
m_Detector_listIsSet = false;
m_Detector_settingsIsSet = false;
m_Image_format_settingsIsSet = false;
m_Instrument_metadataIsSet = false;
m_Data_processing_settingsIsSet = false;
m_MeasurementIsSet = false;
m_BrokerIsSet = false;
m_FpgaIsSet = false;
@@ -48,7 +53,7 @@ bool Jfjoch_statistics::validate(std::stringstream& msg, const std::string& path
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Jfjoch_statistics" : pathPrefix;
if (fpgaIsSet())
{
const std::vector<org::openapitools::server::model::Fpga_status_inner>& value = m_Fpga;
@@ -103,6 +108,21 @@ bool Jfjoch_statistics::operator==(const Jfjoch_statistics& rhs) const
((!detectorIsSet() && !rhs.detectorIsSet()) || (detectorIsSet() && rhs.detectorIsSet() && getDetector() == rhs.getDetector())) &&
((!detectorListIsSet() && !rhs.detectorListIsSet()) || (detectorListIsSet() && rhs.detectorListIsSet() && getDetectorList() == rhs.getDetectorList())) &&
((!detectorSettingsIsSet() && !rhs.detectorSettingsIsSet()) || (detectorSettingsIsSet() && rhs.detectorSettingsIsSet() && getDetectorSettings() == rhs.getDetectorSettings())) &&
((!imageFormatSettingsIsSet() && !rhs.imageFormatSettingsIsSet()) || (imageFormatSettingsIsSet() && rhs.imageFormatSettingsIsSet() && getImageFormatSettings() == rhs.getImageFormatSettings())) &&
((!instrumentMetadataIsSet() && !rhs.instrumentMetadataIsSet()) || (instrumentMetadataIsSet() && rhs.instrumentMetadataIsSet() && getInstrumentMetadata() == rhs.getInstrumentMetadata())) &&
((!dataProcessingSettingsIsSet() && !rhs.dataProcessingSettingsIsSet()) || (dataProcessingSettingsIsSet() && rhs.dataProcessingSettingsIsSet() && getDataProcessingSettings() == rhs.getDataProcessingSettings())) &&
((!measurementIsSet() && !rhs.measurementIsSet()) || (measurementIsSet() && rhs.measurementIsSet() && getMeasurement() == rhs.getMeasurement())) &&
@@ -127,6 +147,16 @@ void to_json(nlohmann::json& j, const Jfjoch_statistics& o)
j = nlohmann::json::object();
if(o.detectorIsSet())
j["detector"] = o.m_Detector;
if(o.detectorListIsSet())
j["detector_list"] = o.m_Detector_list;
if(o.detectorSettingsIsSet())
j["detector_settings"] = o.m_Detector_settings;
if(o.imageFormatSettingsIsSet())
j["image_format_settings"] = o.m_Image_format_settings;
if(o.instrumentMetadataIsSet())
j["instrument_metadata"] = o.m_Instrument_metadata;
if(o.dataProcessingSettingsIsSet())
j["data_processing_settings"] = o.m_Data_processing_settings;
if(o.measurementIsSet())
j["measurement"] = o.m_Measurement;
if(o.brokerIsSet())
@@ -145,6 +175,31 @@ void from_json(const nlohmann::json& j, Jfjoch_statistics& o)
j.at("detector").get_to(o.m_Detector);
o.m_DetectorIsSet = true;
}
if(j.find("detector_list") != j.end())
{
j.at("detector_list").get_to(o.m_Detector_list);
o.m_Detector_listIsSet = true;
}
if(j.find("detector_settings") != j.end())
{
j.at("detector_settings").get_to(o.m_Detector_settings);
o.m_Detector_settingsIsSet = true;
}
if(j.find("image_format_settings") != j.end())
{
j.at("image_format_settings").get_to(o.m_Image_format_settings);
o.m_Image_format_settingsIsSet = true;
}
if(j.find("instrument_metadata") != j.end())
{
j.at("instrument_metadata").get_to(o.m_Instrument_metadata);
o.m_Instrument_metadataIsSet = true;
}
if(j.find("data_processing_settings") != j.end())
{
j.at("data_processing_settings").get_to(o.m_Data_processing_settings);
o.m_Data_processing_settingsIsSet = true;
}
if(j.find("measurement") != j.end())
{
j.at("measurement").get_to(o.m_Measurement);
@@ -185,6 +240,91 @@ void Jfjoch_statistics::unsetDetector()
{
m_DetectorIsSet = false;
}
org::openapitools::server::model::Detector_list Jfjoch_statistics::getDetectorList() const
{
return m_Detector_list;
}
void Jfjoch_statistics::setDetectorList(org::openapitools::server::model::Detector_list const& value)
{
m_Detector_list = value;
m_Detector_listIsSet = true;
}
bool Jfjoch_statistics::detectorListIsSet() const
{
return m_Detector_listIsSet;
}
void Jfjoch_statistics::unsetDetector_list()
{
m_Detector_listIsSet = false;
}
org::openapitools::server::model::Detector_settings Jfjoch_statistics::getDetectorSettings() const
{
return m_Detector_settings;
}
void Jfjoch_statistics::setDetectorSettings(org::openapitools::server::model::Detector_settings const& value)
{
m_Detector_settings = value;
m_Detector_settingsIsSet = true;
}
bool Jfjoch_statistics::detectorSettingsIsSet() const
{
return m_Detector_settingsIsSet;
}
void Jfjoch_statistics::unsetDetector_settings()
{
m_Detector_settingsIsSet = false;
}
org::openapitools::server::model::Image_format_settings Jfjoch_statistics::getImageFormatSettings() const
{
return m_Image_format_settings;
}
void Jfjoch_statistics::setImageFormatSettings(org::openapitools::server::model::Image_format_settings const& value)
{
m_Image_format_settings = value;
m_Image_format_settingsIsSet = true;
}
bool Jfjoch_statistics::imageFormatSettingsIsSet() const
{
return m_Image_format_settingsIsSet;
}
void Jfjoch_statistics::unsetImage_format_settings()
{
m_Image_format_settingsIsSet = false;
}
org::openapitools::server::model::Instrument_metadata Jfjoch_statistics::getInstrumentMetadata() const
{
return m_Instrument_metadata;
}
void Jfjoch_statistics::setInstrumentMetadata(org::openapitools::server::model::Instrument_metadata const& value)
{
m_Instrument_metadata = value;
m_Instrument_metadataIsSet = true;
}
bool Jfjoch_statistics::instrumentMetadataIsSet() const
{
return m_Instrument_metadataIsSet;
}
void Jfjoch_statistics::unsetInstrument_metadata()
{
m_Instrument_metadataIsSet = false;
}
org::openapitools::server::model::Spot_finding_settings Jfjoch_statistics::getDataProcessingSettings() const
{
return m_Data_processing_settings;
}
void Jfjoch_statistics::setDataProcessingSettings(org::openapitools::server::model::Spot_finding_settings const& value)
{
m_Data_processing_settings = value;
m_Data_processing_settingsIsSet = true;
}
bool Jfjoch_statistics::dataProcessingSettingsIsSet() const
{
return m_Data_processing_settingsIsSet;
}
void Jfjoch_statistics::unsetData_processing_settings()
{
m_Data_processing_settingsIsSet = false;
}
org::openapitools::server::model::Measurement_statistics Jfjoch_statistics::getMeasurement() const
{
return m_Measurement;

View File

@@ -23,7 +23,12 @@
#include "Detector_status.h"
#include "Broker_status.h"
#include "Measurement_statistics.h"
#include "Spot_finding_settings.h"
#include "Detector_list.h"
#include "Fpga_status_inner.h"
#include "Image_format_settings.h"
#include "Detector_settings.h"
#include "Instrument_metadata.h"
#include <vector>
#include <nlohmann/json.hpp>
@@ -73,6 +78,41 @@ public:
/// <summary>
///
/// </summary>
org::openapitools::server::model::Detector_list getDetectorList() const;
void setDetectorList(org::openapitools::server::model::Detector_list const& value);
bool detectorListIsSet() const;
void unsetDetector_list();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Detector_settings getDetectorSettings() const;
void setDetectorSettings(org::openapitools::server::model::Detector_settings const& value);
bool detectorSettingsIsSet() const;
void unsetDetector_settings();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Image_format_settings getImageFormatSettings() const;
void setImageFormatSettings(org::openapitools::server::model::Image_format_settings const& value);
bool imageFormatSettingsIsSet() const;
void unsetImage_format_settings();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Instrument_metadata getInstrumentMetadata() const;
void setInstrumentMetadata(org::openapitools::server::model::Instrument_metadata const& value);
bool instrumentMetadataIsSet() const;
void unsetInstrument_metadata();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Spot_finding_settings getDataProcessingSettings() const;
void setDataProcessingSettings(org::openapitools::server::model::Spot_finding_settings const& value);
bool dataProcessingSettingsIsSet() const;
void unsetData_processing_settings();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Measurement_statistics getMeasurement() const;
void setMeasurement(org::openapitools::server::model::Measurement_statistics const& value);
bool measurementIsSet() const;
@@ -104,6 +144,16 @@ public:
protected:
org::openapitools::server::model::Detector_status m_Detector;
bool m_DetectorIsSet;
org::openapitools::server::model::Detector_list m_Detector_list;
bool m_Detector_listIsSet;
org::openapitools::server::model::Detector_settings m_Detector_settings;
bool m_Detector_settingsIsSet;
org::openapitools::server::model::Image_format_settings m_Image_format_settings;
bool m_Image_format_settingsIsSet;
org::openapitools::server::model::Instrument_metadata m_Instrument_metadata;
bool m_Instrument_metadataIsSet;
org::openapitools::server::model::Spot_finding_settings m_Data_processing_settings;
bool m_Data_processing_settingsIsSet;
org::openapitools::server::model::Measurement_statistics m_Measurement;
bool m_MeasurementIsSet;
org::openapitools::server::model::Broker_status m_Broker;

View File

@@ -566,6 +566,7 @@ components:
- height
- serial_number
- base_ipv4_addr
- udp_interface_count
properties:
id:
type: integer
@@ -820,6 +821,16 @@ components:
properties:
detector:
$ref: '#/components/schemas/detector_status'
detector_list:
$ref: '#/components/schemas/detector_list'
detector_settings:
$ref: '#/components/schemas/detector_settings'
image_format_settings:
$ref: '#/components/schemas/image_format_settings'
instrument_metadata:
$ref: '#/components/schemas/instrument_metadata'
data_processing_settings:
$ref: '#/components/schemas/spot_finding_settings'
measurement:
$ref: '#/components/schemas/measurement_statistics'
broker:

File diff suppressed because one or more lines are too long

View File

@@ -69,6 +69,7 @@ ADD_LIBRARY(JFJochCommon STATIC
DetectorSettings.h
AzimuthalIntegrationSettings.cpp
AzimuthalIntegrationSettings.h
CheckPath.h
)
TARGET_LINK_LIBRARIES(JFJochCommon JFJochLogger Compression JFCalibration Threads::Threads -lrt )

21
common/CheckPath.h Normal file
View File

@@ -0,0 +1,21 @@
// Copyright (2019-2024) Paul Scherrer Institute
#ifndef JFJOCH_CHECKPATH_H
#define JFJOCH_CHECKPATH_H
#include <string>
#include "JFJochException.h"
inline void CheckPath(const std::string &s) {
if (s.front() == '/')
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with slash");
if (s.substr(0,3) == "../")
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with ../");
if (s.find("/../") != std::string::npos)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot contain /../");
}
#endif //JFJOCH_CHECKPATH_H

View File

@@ -5,12 +5,12 @@
#include "DatasetSettings.h"
#include "Definitions.h"
#include "JFJochException.h"
#include "CheckPath.h"
#define check_max(param, val, max) if ((val) > (max)) throw JFJochException(JFJochExceptionCategory::InputParameterAboveMax, param)
#define check_min(param, val, min) if ((val) < (min)) throw JFJochException(JFJochExceptionCategory::InputParameterBelowMin, param)
#define check_finite(param, val) if (!std::isfinite(val)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, param)
DatasetSettings::DatasetSettings() {
photon_energy_keV = WVL_1A_IN_KEV;
detector_distance_mm = 100;
@@ -69,21 +69,13 @@ DatasetSettings &DatasetSettings::DetectorDistance_mm(float input) {
}
DatasetSettings &DatasetSettings::FilePrefix(std::string input) {
// File prefix with front slash is not allowed for security reasons
if (input.front() == '/')
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with slash");
if (input.substr(0,3) == "../")
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with ../");
if (input.find("/../") != std::string::npos)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot contain /../");
CheckPath(input);
if ((input.find("_master.h5") == input.length() - 10) && (input.length() > 10))
file_prefix = input.substr(0, input.length() - 10);
else
file_prefix = input;
return *this;
}

View File

@@ -345,9 +345,19 @@ proc create_root_design { parentCell } {
set axis_interconnect_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_interconnect:2.1 axis_interconnect_0 ]
set_property -dict [ list \
CONFIG.ARB_ALGORITHM {3} \
CONFIG.ARB_ON_MAX_XFERS {0} \
CONFIG.ARB_ON_NUM_CYCLES {4} \
CONFIG.ARB_ON_TLAST {1} \
CONFIG.M00_FIFO_DEPTH {512} \
CONFIG.M00_HAS_REGSLICE {1} \
CONFIG.NUM_MI {1} \
CONFIG.NUM_SI {2} \
CONFIG.S00_FIFO_DEPTH {1024} \
CONFIG.S00_FIFO_MODE {1} \
CONFIG.S00_HAS_REGSLICE {1} \
CONFIG.S01_FIFO_DEPTH {1024} \
CONFIG.S01_FIFO_MODE {1} \
CONFIG.S01_HAS_REGSLICE {1} \
] $axis_interconnect_0
# Create instance: clk_wiz_0, and set properties

View File

@@ -55,6 +55,8 @@ proc create_hier_cell_mac_4x10g { parentCell nameHier } {
set axis_interconnect_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_interconnect:2.1 axis_interconnect_0 ]
set_property -dict [ list \
CONFIG.ARB_ALGORITHM {3} \
CONFIG.ARB_ON_MAX_XFERS {0} \
CONFIG.ARB_ON_NUM_CYCLES {4} \
CONFIG.ARB_ON_TLAST {1} \
CONFIG.ENABLE_ADVANCED_OPTIONS {0} \
CONFIG.M00_FIFO_DEPTH {256} \

View File

@@ -19,6 +19,7 @@
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@vitejs/plugin-react-swc": "^3.7.0",
"lodash": "^4.17.21",
"plotly.js": "^2.35.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -30,6 +31,7 @@
"vite-tsconfig-paths": "^5.0.1"
},
"devDependencies": {
"@types/lodash": "^4.17.10",
"openapi-typescript-codegen": "^0.25.0"
}
},
@@ -2408,6 +2410,12 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
},
"node_modules/@types/lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
"dev": true
},
"node_modules/@types/mapbox__point-geometry": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz",
@@ -5840,6 +5848,11 @@
"node": ">=6.11.5"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
@@ -10510,6 +10523,12 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
},
"@types/lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
"dev": true
},
"@types/mapbox__point-geometry": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz",
@@ -13211,6 +13230,11 @@
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
"peer": true
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",

View File

@@ -16,6 +16,7 @@
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@vitejs/plugin-react-swc": "^3.7.0",
"lodash": "^4.17.21",
"plotly.js": "^2.35.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -53,6 +54,7 @@
]
},
"devDependencies": {
"@types/lodash": "^4.17.10",
"openapi-typescript-codegen": "^0.25.0"
}
}

View File

@@ -21,6 +21,7 @@ import FpgaStatus from "./components/FpgaStatus";
import {PlotType} from "./components/DataProcessingPlot";
import {broker_status, DefaultService, OpenAPI} from "./openapi";
import {jfjoch_statistics} from "./openapi";
import DataCollection from "./components/DataCollection";
const jfjoch_theme = createTheme({
palette: {
@@ -36,6 +37,7 @@ type MyState = {
show_roi_setup: boolean,
show_fpga_status: boolean,
connection_error: boolean,
show_data_collection: boolean
s: jfjoch_statistics
}
@@ -51,6 +53,7 @@ class App extends Component<MyProps, MyState> {
show_roi_setup: false,
show_fpga_status: false,
connection_error: true,
show_data_collection: false,
s: {}
}
@@ -91,6 +94,10 @@ class App extends Component<MyProps, MyState> {
this.setState({show_fpga_status: event.target.checked});
}
showDataCollectionToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({show_data_collection: event.target.checked});
}
renderTitleWithSwitch = (name: string, checked: boolean, func: ((event: React.ChangeEvent<HTMLInputElement>) => void)) => {
return <Grid item xs={12}>
<Paper style={{textAlign: 'center'}} sx={{height: 60, width: '100%'}} component={Stack}
@@ -132,13 +139,14 @@ class App extends Component<MyProps, MyState> {
<DataProcessingPlots default_tab={"12"} height={550} type={PlotType.BKG_ESTIMATE}/>
</Grid>
<Grid item xs={4}>
<MeasurementStatistics s={(this.state.s.measurement === undefined) ? {} : this.state.s.measurement}/>
<MeasurementStatistics
s={(this.state.s.measurement === undefined) ? {} : this.state.s.measurement}/>
</Grid>
<Grid item xs={8}>
<DataProcessingPlots default_tab={"1"} height={700} type={PlotType.INDEXING_RATE}/>
</Grid>
<Grid item xs={4}>
<DataProcessingSettings/>
<DataProcessingSettings s={this.state.s.data_processing_settings} update={this.getValues}/>
</Grid>
{
this.renderTitleWithSwitch("Live image preview", this.state.show_preview, this.showPreviewToggle)
@@ -148,33 +156,46 @@ class App extends Component<MyProps, MyState> {
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("JUNGFRAU module calibration",
this.state.show_module_calibration, this.showModuleCalibrationToggle)
this.renderTitleWithSwitch("Data collection",
this.state.show_data_collection, this.showDataCollectionToggle)
}
<Grid item xs={12}>
{this.state.show_module_calibration ? <Calibration s={this.state.s.calibration}/> : ""}
</Grid><br/><br/>
<Grid item xs={2}/>
<Grid item xs={8}>
{this.state.show_data_collection ? <DataCollection frame_time_us={
this.state.s.detector_settings?.frame_time_us ?? 500
}/> : ""}
</Grid>
<Grid item xs={2}/>
<br/><br/>
{
this.renderTitleWithSwitch("Jungfraujoch expert configuration",
this.state.show_detector_setup, this.showDetectorSetupToggle)
}
<Grid item xs={4}>
{this.state.show_detector_setup ? <DetectorSettings/> : ""}
</Grid>
<Grid item xs={4}>
{this.state.show_detector_setup ?
<Stack spacing={2}>
<DetectorSelection/>
<DetectorStatus s={this.state.s.detector}/>
</Stack> : ""}
{this.state.show_detector_setup ? <DetectorSettings s={this.state.s.detector_settings}/> : ""}
</Grid>
<Grid item xs={4}>
{this.state.show_detector_setup ?
<Stack spacing={2}>
<ImageFormatSettings/>
<InstrumentMetadata/>
<DetectorSelection s={this.state.s.detector_list}/>
<DetectorStatus s={this.state.s.detector}/>
</Stack> : ""}
</Grid>
<Grid item xs={4}>
{this.state.show_detector_setup ?
<Stack spacing={2}>
<ImageFormatSettings s={this.state.s.image_format_settings}/>
<InstrumentMetadata s={this.state.s.instrument_metadata}/>
</Stack> : ""}
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("JUNGFRAU module calibration",
this.state.show_module_calibration, this.showModuleCalibrationToggle)
}
<Grid item xs={12}>
{this.state.show_module_calibration ? <Calibration s={this.state.s.calibration}/> : ""}
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("Region of interest (ROI)",

View File

@@ -0,0 +1,247 @@
import React from 'react';
import Paper from '@mui/material/Paper';
import {Alert, SnackbarCloseReason, Stack, TextField} from "@mui/material";
import NumberTextField from "./NumberTextField";
import {ApiError, dataset_settings, DefaultService} from "../openapi";
import Button from "@mui/material/Button";
import Snackbar from '@mui/material/Snackbar';
type MyProps = {
frame_time_us: number
};
type MyState = {
s: dataset_settings,
beam_x_pxl_err: boolean,
beam_y_pxl_err: boolean,
detector_distance_mm_err: boolean,
incident_energy_kev_err: boolean,
images_per_trigger_err: boolean,
image_time_us_err: boolean,
image_time_us_mult_err: boolean,
ntrigger_err: boolean,
snackbar_open: boolean,
start_success: boolean,
start_error?: string
};
class DataCollection extends React.Component<MyProps, MyState> {
state : MyState = {
s : {
beam_x_pxl: 0,
beam_y_pxl: 0,
detector_distance_mm: 100,
incident_energy_keV: 12.398,
images_per_trigger: 1,
image_time_us: this.props.frame_time_us,
ntrigger: 1
},
beam_x_pxl_err: false,
beam_y_pxl_err: false,
detector_distance_mm_err: false,
incident_energy_kev_err: false,
images_per_trigger_err: false,
image_time_us_err: false,
image_time_us_mult_err: false,
ntrigger_err: false,
snackbar_open: false,
start_success: false
}
startButton = () => {
DefaultService.postStart(this.state.s)
.then(() => {
this.setState({
snackbar_open: true,
start_success: true
});
}).catch(error => {
let err : string = "Unknown error";
if (error instanceof ApiError)
err = `${error.status}: ${error.statusText}`
this.setState({
snackbar_open: true,
start_success: false,
start_error: err
});
});
}
error() : boolean {
return this.state.beam_x_pxl_err
|| this.state.beam_y_pxl_err
|| this.state.detector_distance_mm_err
|| this.state.incident_energy_kev_err
|| this.state.image_time_us_err
|| this.state.images_per_trigger_err
|| this.state.ntrigger_err;
}
handleClose = (event?: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) => {
if (reason === 'clickaway') {
return;
}
this.setState({snackbar_open: false});
};
render() {
return <Paper style={{textAlign: 'center'}} sx={{ width: '100%'}}>
<br/>
<Stack spacing={5} sx={{
justifyContent: "center",
alignItems: "center",
}}>
<TextField label={"File prefix"}
variant="outlined"
onChange={
(event: React.ChangeEvent<HTMLInputElement>) => {
this.setState(prevState => ({
s: {...prevState.s, file_prefix: event.target.value}
}));
}
}
value={this.state.s.file_prefix}
sx={{width:"90%"}}
/>
<Stack direction="row" spacing={2} sx={{width: '90%'}}>
<NumberTextField
label={"Number of images per trigger"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, images_per_trigger: val},
images_per_trigger_err: err
}
));
}}
min={1}
default={this.state.s.images_per_trigger}
/>
<NumberTextField
label={"Number of triggers"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, ntrigger: val},
ntrigger_err: err
}
));
}}
min={1}
default={this.state.s.ntrigger}
/>
<NumberTextField
label={"Image time"}
callback={(val: number, err: boolean) => {
let image_time_us = Math.round(val * 1000.0);
// image_time_us_mult_err makes sense only if there is no non-sense condition
let image_time_us_mult_err = !err
&& (this.props.frame_time_us > 0)
&& (image_time_us % this.props.frame_time_us != 0);
this.setState(prevState => ({
s: {...prevState.s,
image_time_us: image_time_us
},
image_time_us_err: err,
image_time_us_mult_err: image_time_us_mult_err
}
));
}}
units={"ms"}
float={true}
min={this.props.frame_time_us / 1000.0}
default={(this.state.s.image_time_us ?? 500) / 1000.0}
/>
</Stack>
<Stack direction="row" spacing={2} sx={{width: '90%'}}>
<NumberTextField
label={"Beam X [pxl]"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, beam_x_pxl: val},
beam_x_pxl_err: err
}
));
}}
units={"pxl"}
float={true}
default={this.state.s.beam_x_pxl}
/>
<NumberTextField
label={"Beam Y"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, beam_y_pxl: val},
beam_y_pxl_err: err
}
));
}}
units={"pxl"}
float={true}
default={this.state.s.beam_y_pxl}
/>
<NumberTextField
label={"Detector distance"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, detector_distance_mm: val},
detector_distance_mm_err: err
}
));
}}
units={"mm"}
min={0.1}
float={true}
default={this.state.s.detector_distance_mm}
/>
<NumberTextField
label={"Energy"}
callback={(val: number, err: boolean) => {
this.setState(prevState => ({
s: {...prevState.s, incident_energy_keV: val},
incident_energy_kev_err: err
}
));
}}
min={0.1}
max={100.0}
units={"keV"}
float={true}
default={this.state.s.incident_energy_keV}
/>
</Stack>
<div style={{color: "red"}}>
{this.state.image_time_us_mult_err ? <>Image time must be multiple of frame time ({this.props.frame_time_us} &micro;s)</> : <br/>}
</div>
<Button
color="primary"
onClick={this.startButton}
variant="contained"
disableElevation
disabled={this.error()}
>
Start
</Button>
<Snackbar open={this.state.snackbar_open}
autoHideDuration={6000}
onClose={this.handleClose}>
<Alert
onClose={this.handleClose}
severity={this.state.start_success ? "success" : "error"}
variant="filled"
sx={{ width: '100%' }}
>
{this.state.start_success ? "Started" : this.state.start_error}
</Alert>
</Snackbar>
</Stack>
<br/>
</Paper>
}
}
export default DataCollection;

View File

@@ -4,15 +4,16 @@ import Paper from '@mui/material/Paper';
import {Grid, Slider, Switch, Typography} from "@mui/material";
import {DefaultService, spot_finding_settings} from "../openapi";
type MyProps = {};
type MyProps = {
s?: spot_finding_settings,
update: () => void
};
type MyState = {
s: spot_finding_settings,
connection_error: boolean;
s: spot_finding_settings
}
class DataProcessingSettings extends Component<MyProps, MyState> {
interval: ReturnType<typeof setInterval> | undefined;
state : MyState = {
s: {
enable: true,
@@ -26,134 +27,71 @@ class DataProcessingSettings extends Component<MyProps, MyState> {
high_resolution_limit: 2.5,
low_resolution_limit: 20.0,
indexing_tolerance: 0.05
},
connection_error: true
}
}
putValues() {
DefaultService.putConfigSpotFinding(this.state.s)
.catch(error => console.log(error) );
}
putValues2(x: MyState) {
DefaultService.putConfigSpotFinding(x.s)
putValues(x: spot_finding_settings) {
DefaultService.putConfigSpotFinding(x)
.catch(error => console.log(error) );
}
getValues() {
DefaultService.getConfigSpotFinding()
.then(data => this.setState({s: data, connection_error: false}))
.catch(error => {
// this.setState({connection_error: true});
});
if (this.props.s !== undefined)
this.setState({s: this.props.s});
}
componentDidMount() {
this.getValues();
this.interval = setInterval(() => this.getValues(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
componentDidUpdate(prevProps: Readonly<MyProps>) {
if ((this.props.s !== undefined) && (prevProps.s != this.props.s))
this.setState({s: this.props.s});
}
setPhotonCountThreshold = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
photon_count_threshold: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, photon_count_threshold: newValue as number});
this.props.update();
}
setSignalToNoiseThreshold = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
signal_to_noise_threshold: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, signal_to_noise_threshold: newValue as number});
this.props.update();
}
setMinPixPerSpot = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
min_pix_per_spot: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, min_pix_per_spot: newValue as number});
this.props.update();
}
setIndexingTolerance = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
indexing_tolerance: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, indexing_tolerance: newValue as number});
this.props.update();
}
setHighResolutionLimit = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
high_resolution_limit: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, high_resolution_limit: newValue as number});
this.props.update();
}
enableSpotFindingToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.enable = event.target.checked;
this.putValues2(x);
this.getValues();
this.putValues({...this.state.s, enable: event.target.checked});
this.props.update();
}
enableIndexingToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.indexing = event.target.checked;
this.putValues2(x);
this.getValues();
this.putValues({...this.state.s, indexing: event.target.checked});
this.props.update();
}
enableFilterPowderRingToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
let x = this.state;
x.s.filter_powder_rings = event.target.checked;
this.putValues2(x);
this.getValues();
this.putValues({...this.state.s, filter_powder_rings: event.target.checked});
this.props.update();
}
setMinSpotCountPowderRing = (event: Event, newValue: number | number[]) => {
this.setState(prevState => (
{
s : {
...prevState.s,
min_spot_count_powder_ring: newValue as number
}
}
));
this.putValues();
this.getValues();
this.putValues({...this.state.s, min_spot_count_powder_ring: newValue as number});
this.props.update();
}
render() {
@@ -163,50 +101,49 @@ class DataProcessingSettings extends Component<MyProps, MyState> {
<Grid item xs={1}/>
<Grid item xs={10}>
<br/><strong>Spot finding parameters</strong><br/><br/>
<Switch onChange={this.enableSpotFindingToggle} checked={this.state.s.enable}
disabled={this.state.connection_error}/>
<Switch onChange={this.enableSpotFindingToggle} checked={this.state.s.enable}/>
Spot finding
<br/><br/>
<Typography gutterBottom> Count threshold </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable}
<Slider disabled={!this.state.s.enable}
value={Number(this.state.s.photon_count_threshold)}
onChange={this.setPhotonCountThreshold}
min={1} max={50} step={1} valueLabelDisplay="auto"/>
<br/><Typography> Signal-to-noise threshold </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable}
<Slider disabled={!this.state.s.enable}
value={Number(this.state.s.signal_to_noise_threshold)}
onChange={this.setSignalToNoiseThreshold}
min={2} max={10} step={0.5} valueLabelDisplay="auto"/>
<br/><Typography> Minimum pixel / spot </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable}
<Slider disabled={!this.state.s.enable}
value={Number(this.state.s.min_pix_per_spot)}
onChange={this.setMinPixPerSpot}
min={1} max={8} step={1} valueLabelDisplay="auto"/>
<Typography> High resolution limit [&#8491;] </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable}
<Slider disabled={!this.state.s.enable}
value={Number(this.state.s.high_resolution_limit)}
onChange={this.setHighResolutionLimit}
min={1} max={5} step={0.2} valueLabelDisplay="auto"/>
<br/><br/>
<Switch onChange={this.enableFilterPowderRingToggle}
checked={this.state.s.filter_powder_rings}
disabled={this.state.connection_error || !this.state.s.enable}/>
disabled={!this.state.s.enable}/>
Filter spots in powder rings (<i>e.g.</i>, ice)
<br/><br/>
<Typography> Min spots to filter powder ring </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable || !this.state.s.filter_powder_rings}
<Slider disabled={!this.state.s.enable || !this.state.s.filter_powder_rings}
value={Number(this.state.s.filter_powder_rings)}
onChange={this.setMinSpotCountPowderRing}
min={5} max={50} step={1} valueLabelDisplay="auto"/>
<br/> <br/>
<Switch onChange={this.enableIndexingToggle} checked={this.state.s.indexing}
disabled={this.state.connection_error || !this.state.s.enable}/>
disabled={!this.state.s.enable}/>
Indexing <br/><br/>
<Typography> Indexing spot acceptance tolerance </Typography>
<Slider disabled={this.state.connection_error || !this.state.s.enable || !this.state.s.indexing}
<Slider disabled={!this.state.s.enable || !this.state.s.indexing}
value={Number(this.state.s.indexing_tolerance)}
onChange={this.setIndexingTolerance}
min={0.0} max={0.3} step={0.01} valueLabelDisplay="auto"/>

View File

@@ -9,54 +9,32 @@ import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import {DefaultService, detector_list} from "../openapi";
type MyProps = {}
type MyProps = {
s?: detector_list
}
type MyState = {
s: detector_list,
choice: string,
connection_error: boolean
choice: string
};
type MapElement = {
id: number
name: string
}
type DetectorTableElement = {
title: string
val: string
}
class DetectorSelection extends Component<MyProps, MyState> {
interval: ReturnType<typeof setInterval> | undefined;
state : MyState = {
s: {
detectors: [],
current_id: 0
},
choice: "0",
connection_error: true
choice: "0"
}
getValuesInitial() {
DefaultService.getConfigSelectDetector()
.then(data => this.setState({
s: data,
choice: String(data.current_id),
connection_error: false
}))
.catch(error => {
this.setState({connection_error: true});
});
}
getValues() {
DefaultService.getConfigSelectDetector()
.then(data => this.setState({
s: data,
connection_error: false
}))
.catch(error => {
this.setState({connection_error: true});
});
}
componentDidMount() {
this.getValuesInitial();
this.interval = setInterval(() => this.getValues(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
if (this.props.s !== undefined)
this.setState({choice: this.props.s.current_id.toString()});
}
uploadButton = () => { this.putValues(); }
@@ -67,35 +45,55 @@ class DetectorSelection extends Component<MyProps, MyState> {
putValues = () => {
DefaultService.putConfigSelectDetector({id: Number(this.state.choice)})
.catch(error => console.log(error) );
.catch(error => {} );
}
detector_info = (curr_id: number) => {
let x = this.state.s.detectors[curr_id];
detector_info = (curr_id: number) : JSX.Element => {
if (this.props.s === undefined)
return <div>Not connected</div>
let x = this.props.s.detectors[curr_id];
let arr: DetectorTableElement[] = [
{title: "Current Detector", val: x.description},
{title: "Serial number", val: x.serial_number},
{title: "Size", val: `${x.width} x ${x.height}`},
{title: "Modules", val: `${x.nmodules}`},
{title: "UDP interfaces", val: `${x.udp_interface_count}`}
];
return <TableContainer component={Paper} style={{marginLeft: "auto", marginRight: "auto"}}>
<Table size="small" aria-label="simple table">
<TableBody>
<TableRow>
<TableCell component="th" scope="row"> Current detector: </TableCell>
<TableCell align="right">{x.description}</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row"> Serial number: </TableCell>
<TableCell align="right">{x.serial_number}</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row"> Size: </TableCell>
<TableCell align="right">{x.width} x {x.height} pxl</TableCell>
</TableRow>
{
arr.map(d => (
<TableRow>
<TableCell component="th" scope="row">{d.title}: </TableCell>
<TableCell align="right">{d.val}</TableCell>
</TableRow>
))
}
</TableBody>
</Table>
</TableContainer>
}
detector_list() : MapElement[] {
let v: MapElement[] = [];
if (this.props.s !== undefined) {
let id: number = this.props.s.current_id;
v = this.props.s.detectors.map(d => ({
id: d.id,
name: `${d.description} (${d.width}x${d.height} pxl) ` + ((d.id === id) ? "*** CURRENT ***" : "")
}));
}
return v;
}
render() {
return <Paper style={{textAlign: 'center'}} sx={{height: 400, width: '100%'}}>
return <Paper style={{textAlign: 'center'}} sx={{height: 430, width: '100%'}}>
<Grid container spacing={0}>
@@ -103,8 +101,9 @@ class DetectorSelection extends Component<MyProps, MyState> {
<Grid item xs={10}>
<br/><strong>Detector selection </strong>
<br/><br/>
{(this.state.connection_error || (this.state.s.detectors.length <= Number(this.state.s.current_id))) ?
"" : this.detector_info(this.state.s.current_id)}
{((this.props.s === undefined)
|| (this.props.s.detectors.length <= Number(this.props.s.current_id))) ?
"" : this.detector_info(this.props.s.current_id)}
<br/><br/>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Detector</InputLabel>
@@ -114,18 +113,14 @@ class DetectorSelection extends Component<MyProps, MyState> {
value={this.state.choice}
label="Detector"
onChange={this.handleChange}
disabled={this.state.connection_error}
disabled={this.props.s === undefined}
>
{
(this.state.s.detectors !== undefined) ?
this.state.s.detectors.map(d => (
<MenuItem value={d.id}>{d.description} ({d.width}x{d.height} pxl)</MenuItem>))
: ""}
{this.detector_list().map(d => (<MenuItem value={d.id}> {d.name} </MenuItem>))}
</Select>
</FormControl><br/><br/>
<Button color="primary" onClick={this.uploadButton} variant="contained" disableElevation
disabled={this.state.connection_error}>CHANGE DETECTOR</Button>
disabled={this.props.s === undefined}>CHANGE DETECTOR</Button>
<br/><br/>
</Grid>

View File

@@ -9,11 +9,15 @@ import Select, {SelectChangeEvent} from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import {DefaultService, detector_settings, detector_timing} from "../openapi";
import NumberTextField from "./NumberTextField";
import _ from "lodash";
type MyProps = {}
type MyProps = {
s?: detector_settings
}
type MyState = {
s: detector_settings,
last_downloaded_s: detector_settings,
storage_cell_list_value: string,
timing_mode_list_value: detector_timing,
frame_time_err: boolean,
@@ -34,7 +38,10 @@ type MyState = {
class DetectorSettings extends Component<MyProps, MyState> {
state : MyState = {
s: {
frame_time_us: 1000,
frame_time_us: 1000
},
last_downloaded_s: {
frame_time_us: 1000
},
timing_mode_list_value: detector_timing.TRIGGER,
storage_cell_list_value: "1",
@@ -53,9 +60,6 @@ class DetectorSettings extends Component<MyProps, MyState> {
download_counter: 0
}
uploadButton = () => { this.putValues(); }
downloadButton = () => { this.getValues(); }
eigerThresholdToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.checked)
this.setState(prevState => ({s : {...prevState.s,
@@ -130,25 +134,41 @@ class DetectorSettings extends Component<MyProps, MyState> {
);
};
getValues = () => {
let c = this.state.download_counter + 1;
DefaultService.getConfigDetector()
.then(data => this.setState({
download_counter: c,
s: data,
storage_cell_list_value: (data.jungfrau_storage_cell_count === undefined)
? "1" : String(data.jungfrau_storage_cell_count),
timing_mode_list_value: (data.timing === undefined) ? detector_timing.TRIGGER : data.timing
}))
.catch(error => {});
console.log(this.state);
getValues() {
if (this.props.s !== undefined) {
let det_set: detector_settings = this.props.s;
if (!_.isEqual(det_set, this.state.last_downloaded_s)) {
this.setState(prevState => ({
download_counter: prevState.download_counter + 1,
s: det_set,
last_downloaded_s: det_set,
storage_cell_list_value: String(det_set.jungfrau_storage_cell_count ?? "1"),
timing_mode_list_value: det_set.timing ?? detector_timing.TRIGGER,
pedestal_g0_frames_err: false,
pedestal_g1_frames_err: false,
pedestal_g2_frames_err: false,
pedestal_g0_rms_limit_err: false,
pedestal_min_image_count_err: false,
storage_cell_delay_err: false,
detector_trigger_delay_err: false,
frame_time_err: false,
count_time_err: false,
internal_frame_generator_images_err: false,
eiger_threshold_err: false,
eiger_threshold_keV_old: 6.0
}));
}
}
}
componentDidMount() {
this.getValues();
}
componentDidUpdate() {
this.getValues();
}
render() {
return <Paper style={{textAlign: 'center'}} sx={{ height: 1150, width: '100%' }}>
@@ -440,9 +460,7 @@ class DetectorSettings extends Component<MyProps, MyState> {
<Grid item xs={3}/>
<Grid item xs={1}/>
<Grid item xs={10}>
<Button color="secondary" onClick={this.downloadButton} variant="contained" disableElevation>
Download</Button>&nbsp;&nbsp;
<Button color="primary" onClick={this.uploadButton} variant="contained" disableElevation
<Button color="primary" onClick={this.putValues} variant="contained" disableElevation
disabled={this.state.count_time_err
|| this.state.frame_time_err
|| this.state.internal_frame_generator_images_err

View File

@@ -1,14 +1,6 @@
import React, {Component} from 'react';
import {
Checkbox,
FormControlLabel,
FormGroup,
Grid,
List,
ListItem, Switch,
Tooltip
} from "@mui/material";
import {Checkbox, FormControlLabel, FormGroup, Grid, List, ListItem, Switch, Tooltip} from "@mui/material";
import Button from "@mui/material/Button";
import Paper from "@mui/material/Paper";
import FormControl from "@mui/material/FormControl";
@@ -17,11 +9,15 @@ import Select, {SelectChangeEvent} from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import {DefaultService, image_format_settings} from "../openapi";
import NumberTextField from "./NumberTextField";
import _ from "lodash";
type MyProps = {}
type MyProps = {
s?: image_format_settings
}
type MyState = {
s: image_format_settings,
last_downloaded_s: image_format_settings,
bit_width_selection: string,
sign_selection: string,
jungfrau_conversion_factor_err: boolean,
@@ -29,18 +25,41 @@ type MyState = {
download_counter: number
}
const default_image_format_settings: image_format_settings = {
summation: true,
geometry_transform: true,
jungfrau_conversion: true,
jungfrau_conversion_factor_keV: undefined,
bit_depth_image: undefined,
signed_output: undefined,
mask_module_edges: true,
mask_chip_edges: true
};
function extractSignForSelection(input: image_format_settings) : string {
if (input.signed_output === undefined)
return 'a';
else if (input.signed_output)
return 's';
else
return 'u';
}
function extractDepthForSelection(input: image_format_settings) : string {
if (input.bit_depth_image === undefined)
return 'a';
else if (input.bit_depth_image === image_format_settings.bit_depth_image._16)
return '16';
else if (input.bit_depth_image === image_format_settings.bit_depth_image._32)
return '32';
else
return "";
}
class ImageFormatSettings extends Component<MyProps, MyState> {
state : MyState = {
s: {
summation: true,
geometry_transform: true,
jungfrau_conversion: true,
jungfrau_conversion_factor_keV: undefined,
bit_depth_image: undefined,
signed_output: undefined,
mask_module_edges: true,
mask_chip_edges: true
},
s: default_image_format_settings,
last_downloaded_s: default_image_format_settings,
jungfrau_conversion_factor_err: false,
jungfrau_conversion_factor_old: 12.4,
bit_width_selection: "a",
@@ -61,7 +80,6 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
}
uploadButton = () => { this.putValues(); }
downloadButton = () => { this.getValues(); }
putValues = () => {
DefaultService.putConfigImageFormat(this.state.s)
@@ -69,24 +87,35 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
this.getValues();
}
getValues = () => {
DefaultService.getConfigImageFormat()
.then(data => {
let old : number = this.state.jungfrau_conversion_factor_old;
if (data.jungfrau_conversion_factor_keV !== undefined)
old = data.jungfrau_conversion_factor_keV;
this.setState({
if (this.props.s !== undefined) {
let format_set: image_format_settings = this.props.s;
if (!_.isEqual(format_set, this.state.last_downloaded_s)) {
this.setState(prevState => ({
s: format_set,
last_downloaded_s: format_set,
jungfrau_conversion_factor_err: false,
download_counter: this.state.download_counter + 1,
jungfrau_conversion_factor_old: old,
s: data
})}).catch(error => {});
download_counter: prevState.download_counter + 1,
jungfrau_conversion_factor_old: format_set.jungfrau_conversion_factor_keV
?? prevState.jungfrau_conversion_factor_old,
bit_width_selection: extractDepthForSelection(format_set),
sign_selection: extractSignForSelection(format_set)
}));
}
}
}
componentDidMount() {
this.getValues();
}
componentDidUpdate() {
this.getValues();
}
handleBitWidthChange = (event: SelectChangeEvent) => {
let val: image_format_settings.bit_depth_image|undefined = undefined;
@@ -305,9 +334,6 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
<Grid item xs={1}/>
<Grid item xs={10}>
<Button color="secondary" onClick={this.downloadButton} variant="contained" disableElevation>
Download
</Button>&nbsp;&nbsp;
<Button color="primary" onClick={this.uploadButton} variant="contained" disableElevation
disabled={this.state.jungfrau_conversion_factor_err}>
Upload

View File

@@ -10,13 +10,24 @@ import {
import Button from "@mui/material/Button";
import Paper from "@mui/material/Paper";
import {DefaultService, instrument_metadata} from "../openapi";
import _ from "lodash";
type MyProps = {}
type MyProps = {
s?: instrument_metadata
}
type MyState = {
s: instrument_metadata
last_downloaded_s: instrument_metadata
};
const default_instrument_metadata: instrument_metadata = {
source_name: "Swiss Light Source",
instrument_name: "X06SA",
source_type: "Synchrotron X-ray Source",
pulsed_source: false
}
const source_types : string[] = [
"Synchrotron X-ray Source",
"Free-Electron Laser",
@@ -29,16 +40,11 @@ const source_types : string[] = [
class ImageFormatSettings extends Component<MyProps, MyState> {
state : MyState = {
s: {
source_name: "Swiss Light Source",
instrument_name: "X06SA",
source_type: "Synchrotron X-ray Source",
pulsed_source: false
}
s: default_instrument_metadata,
last_downloaded_s: default_instrument_metadata
}
uploadButton = () => { this.putValues(); }
downloadButton = () => { this.getValues(); }
putValues = () => {
DefaultService.putConfigInstrument(this.state.s)
@@ -46,16 +52,25 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
this.getValues();
}
getValues = () => {
DefaultService.getConfigInstrument()
.then(data => {
this.setState({s: data})}).catch(error => {});
getValues () {
if (this.props.s !== undefined) {
let instr_metadata: instrument_metadata = this.props.s;
if (!_.isEqual(instr_metadata, this.state.last_downloaded_s))
this.setState({
s: instr_metadata,
last_downloaded_s: instr_metadata
});
}
}
componentDidMount() {
this.getValues();
}
componentDidUpdate() {
this.getValues();
}
render() {
return <Paper style={{textAlign: 'center'}} sx={{ height: 450, width: '100%' }}>
@@ -89,13 +104,8 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
freeSolo
multiple={false}
onChange={(event, newValue: string | null | undefined) => {
console.log(event);
console.log(newValue);
if (typeof newValue === "string") {
this.setState(prevState => ({
s: {...prevState.s, source_type: newValue}
}));
}
if (typeof newValue === "string")
this.setState(prevState => ({s: {...prevState.s, source_type: newValue}}));
}}
inputValue={this.state.s.source_type}
@@ -127,10 +137,6 @@ class ImageFormatSettings extends Component<MyProps, MyState> {
<Grid item xs={1}/>
<Grid item xs={1}/>
<Grid item xs={10}>
<Button color="secondary" onClick={this.downloadButton} variant="contained" disableElevation>
Download
</Button>
&nbsp;&nbsp;
<Button color="primary" onClick={this.uploadButton} variant="contained" disableElevation>
Upload
</Button>

View File

@@ -5,15 +5,25 @@
import type { broker_status } from './broker_status';
import type { calibration_statistics } from './calibration_statistics';
import type { detector_list } from './detector_list';
import type { detector_settings } from './detector_settings';
import type { detector_status } from './detector_status';
import type { fpga_status } from './fpga_status';
import type { image_format_settings } from './image_format_settings';
import type { instrument_metadata } from './instrument_metadata';
import type { measurement_statistics } from './measurement_statistics';
import type { spot_finding_settings } from './spot_finding_settings';
/**
* Pool statistics for Jungfraujoch to reduce transfers between frontend and jfjoch_broker
*/
export type jfjoch_statistics = {
detector?: detector_status;
detector_list?: detector_list;
detector_settings?: detector_settings;
image_format_settings?: image_format_settings;
instrument_metadata?: instrument_metadata;
data_processing_settings?: spot_finding_settings;
measurement?: measurement_statistics;
broker?: broker_status;
fpga?: fpga_status;

View File

@@ -5,7 +5,7 @@
#
export PACKAGE_VERSION_SEM=`head -n1 VERSION`
export FPGA_VERSION="1.0.0-rc.16"
export FPGA_VERSION="1.0.0-rc.17"
export PACKAGE_VERSION=${PACKAGE_VERSION_SEM//-/_}
export PACKAGE_VERSION_PYTHON=${PACKAGE_VERSION_SEM//-rc./rc}
export PACKAGE_VERSION_PYTHON=${PACKAGE_VERSION_PYTHON//-alpha./a}

View File

@@ -7,6 +7,11 @@ Pool statistics for Jungfraujoch to reduce transfers between frontend and jfjoch
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**detector** | [**DetectorStatus**](DetectorStatus.md) | | [optional]
**detector_list** | [**DetectorList**](DetectorList.md) | | [optional]
**detector_settings** | [**DetectorSettings**](DetectorSettings.md) | | [optional]
**image_format_settings** | [**ImageFormatSettings**](ImageFormatSettings.md) | | [optional]
**instrument_metadata** | [**InstrumentMetadata**](InstrumentMetadata.md) | | [optional]
**data_processing_settings** | [**SpotFindingSettings**](SpotFindingSettings.md) | | [optional]
**measurement** | [**MeasurementStatistics**](MeasurementStatistics.md) | | [optional]
**broker** | [**BrokerStatus**](BrokerStatus.md) | | [optional]
**fpga** | [**List[FpgaStatusInner]**](FpgaStatusInner.md) | | [optional]

View File

@@ -22,9 +22,14 @@ from pydantic import BaseModel, ConfigDict
from typing import Any, ClassVar, Dict, List, Optional
from jfjoch_client.models.broker_status import BrokerStatus
from jfjoch_client.models.calibration_statistics_inner import CalibrationStatisticsInner
from jfjoch_client.models.detector_list import DetectorList
from jfjoch_client.models.detector_settings import DetectorSettings
from jfjoch_client.models.detector_status import DetectorStatus
from jfjoch_client.models.fpga_status_inner import FpgaStatusInner
from jfjoch_client.models.image_format_settings import ImageFormatSettings
from jfjoch_client.models.instrument_metadata import InstrumentMetadata
from jfjoch_client.models.measurement_statistics import MeasurementStatistics
from jfjoch_client.models.spot_finding_settings import SpotFindingSettings
from typing import Optional, Set
from typing_extensions import Self
@@ -33,11 +38,16 @@ class JfjochStatistics(BaseModel):
Pool statistics for Jungfraujoch to reduce transfers between frontend and jfjoch_broker
""" # noqa: E501
detector: Optional[DetectorStatus] = None
detector_list: Optional[DetectorList] = None
detector_settings: Optional[DetectorSettings] = None
image_format_settings: Optional[ImageFormatSettings] = None
instrument_metadata: Optional[InstrumentMetadata] = None
data_processing_settings: Optional[SpotFindingSettings] = None
measurement: Optional[MeasurementStatistics] = None
broker: Optional[BrokerStatus] = None
fpga: Optional[List[FpgaStatusInner]] = None
calibration: Optional[List[CalibrationStatisticsInner]] = None
__properties: ClassVar[List[str]] = ["detector", "measurement", "broker", "fpga", "calibration"]
__properties: ClassVar[List[str]] = ["detector", "detector_list", "detector_settings", "image_format_settings", "instrument_metadata", "data_processing_settings", "measurement", "broker", "fpga", "calibration"]
model_config = ConfigDict(
populate_by_name=True,
@@ -81,6 +91,21 @@ class JfjochStatistics(BaseModel):
# override the default output from pydantic by calling `to_dict()` of detector
if self.detector:
_dict['detector'] = self.detector.to_dict()
# override the default output from pydantic by calling `to_dict()` of detector_list
if self.detector_list:
_dict['detector_list'] = self.detector_list.to_dict()
# override the default output from pydantic by calling `to_dict()` of detector_settings
if self.detector_settings:
_dict['detector_settings'] = self.detector_settings.to_dict()
# override the default output from pydantic by calling `to_dict()` of image_format_settings
if self.image_format_settings:
_dict['image_format_settings'] = self.image_format_settings.to_dict()
# override the default output from pydantic by calling `to_dict()` of instrument_metadata
if self.instrument_metadata:
_dict['instrument_metadata'] = self.instrument_metadata.to_dict()
# override the default output from pydantic by calling `to_dict()` of data_processing_settings
if self.data_processing_settings:
_dict['data_processing_settings'] = self.data_processing_settings.to_dict()
# override the default output from pydantic by calling `to_dict()` of measurement
if self.measurement:
_dict['measurement'] = self.measurement.to_dict()
@@ -114,6 +139,11 @@ class JfjochStatistics(BaseModel):
_obj = cls.model_validate({
"detector": DetectorStatus.from_dict(obj["detector"]) if obj.get("detector") is not None else None,
"detector_list": DetectorList.from_dict(obj["detector_list"]) if obj.get("detector_list") is not None else None,
"detector_settings": DetectorSettings.from_dict(obj["detector_settings"]) if obj.get("detector_settings") is not None else None,
"image_format_settings": ImageFormatSettings.from_dict(obj["image_format_settings"]) if obj.get("image_format_settings") is not None else None,
"instrument_metadata": InstrumentMetadata.from_dict(obj["instrument_metadata"]) if obj.get("instrument_metadata") is not None else None,
"data_processing_settings": SpotFindingSettings.from_dict(obj["data_processing_settings"]) if obj.get("data_processing_settings") is not None else None,
"measurement": MeasurementStatistics.from_dict(obj["measurement"]) if obj.get("measurement") is not None else None,
"broker": BrokerStatus.from_dict(obj["broker"]) if obj.get("broker") is not None else None,
"fpga": [FpgaStatusInner.from_dict(_item) for _item in obj["fpga"]] if obj.get("fpga") is not None else None,

View File

@@ -3,6 +3,7 @@
#include "HDF5Writer.h"
#include <nlohmann/json.hpp>
#include "MakeDirectory.h"
#include "../common/CheckPath.h"
HDF5Writer::HDF5Writer(const StartMessage &request)
: start_message(request) {

View File

@@ -17,16 +17,6 @@ inline void MakeDirectory(const std::string &input) {
}
}
inline void CheckPath(const std::string &s) {
if (s.front() == '/')
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with slash");
if (s.substr(0,3) == "../")
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot start with ../");
if (s.find("/../") != std::string::npos)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Path cannot contain /../");
}
#endif //JUNGFRAUJOCH_MAKEDIRECTORY_H