Files
Jungfraujoch/frontend/src/App.tsx
T
2025-09-22 19:49:39 +02:00

250 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, {Component} from 'react';
import {createTheme, CssBaseline, Grid, Stack, Switch, ThemeProvider, Typography} from "@mui/material";
import {indigo, lime} from "@mui/material/colors";
import DataProcessingSettings from "./components/DataProcessingSettings";
import DetectorSettings from "./components/DetectorSettings";
import Calibration from "./components/Calibration";
import StatusBar from "./components/StatusBar";
import DataProcessingPlots from "./components/DataProcessingPlots";
import DetectorSelection from "./components/DetectorSelection";
import MeasurementStatistics from "./components/MeasurementStatistics";
import DetectorStatus from "./components/DetectorStatus";
import Paper from "@mui/material/Paper";
import PreviewImage from "./components/PreviewImage";
import ROI from "./components/ROI";
import ImageFormatSettings from "./components/ImageFormatSettings";
import InstrumentMetadata from "./components/InstrumentMetadata";
import {JFJOCH_VERSION} from "./version";
import FpgaStatus from "./components/FpgaStatus";
import {broker_status, DefaultService, OpenAPI, plot_type} from "./openapi";
import {jfjoch_statistics} from "./openapi";
import DataCollection from "./components/DataCollection";
import ZeroMQPreview from "./components/ZeroMQPreview";
import PixelMask from "./components/PixelMask";
import ErrorMessage from "./components/ErrorMessage";
import FileWriterSettings from "./components/FileWriterSettings";
import AzIntSettings from "./components/AzIntSettings";
import IndexingSettings from "./components/IndexingSettings";
const jfjoch_theme = createTheme({
palette: {
primary: indigo,
secondary: lime,
},
});
type MyState = {
show_detector_setup: boolean,
show_module_calibration: boolean,
show_preview: boolean,
show_roi_setup: boolean,
show_fpga_status: boolean,
connection_error: boolean,
show_data_collection: boolean,
s: jfjoch_statistics
}
type MyProps = {}
class App extends Component<MyProps, MyState> {
interval: ReturnType<typeof setInterval> | undefined;
state : MyState = {
show_detector_setup: false,
show_module_calibration: false,
show_preview: false,
show_roi_setup: false,
show_fpga_status: false,
connection_error: true,
show_data_collection: false,
s: {}
}
getValues() {
DefaultService.getStatistics()
.then(data => this.setState({s: data, connection_error: false}))
.catch(_ => {
this.setState({s: {}, connection_error: true});
});
}
componentWillUnmount() {
clearInterval(this.interval);
}
componentDidMount() {
OpenAPI.BASE='';
this.getValues();
this.interval = setInterval(() => this.getValues(), 1000);
}
showPreviewToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({show_preview: event.target.checked});
}
showDetectorSetupToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({show_detector_setup: event.target.checked});
}
showModuleCalibrationToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({show_module_calibration: event.target.checked});
}
showROISetupToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({show_roi_setup: event.target.checked});
}
showFPGAStatusToggle = (event: React.ChangeEvent<HTMLInputElement>) => {
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}
direction="column" justifyContent="center">
<Grid container spacing={0}>
<Grid xs={1}/>
<Grid xs={10}>
<Typography variant="h5"> {name} </Typography>
</Grid>
<Grid xs={1}>
<Switch checked={checked}
onChange={func}
name="Show detector setup"/>
</Grid>
</Grid>
</Paper>
</Grid>
};
isMeasuring() : boolean {
return (this.state.s.broker !== undefined)
&& (this.state.s.broker.state == broker_status.state.MEASURING);
}
render() {
return <ThemeProvider theme={jfjoch_theme}>
<CssBaseline enableColorScheme/>
<StatusBar s={this.state.s.broker}/> <br/><br/><br/><br/>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<Grid container
justifyContent="center"
alignItems="center"
spacing={3}
sx={{width: "95%"}}>
<Grid item xs={2}/>
<Grid item xs={8}>
<ErrorMessage s={this.state.s.broker}/>
</Grid>
<Grid item xs={2}/>
<Grid item xs={8}>
<DataProcessingPlots height={550} type={plot_type.BKG_ESTIMATE}/>
</Grid>
<Grid item xs={4}>
<MeasurementStatistics
s={(this.state.s.measurement === undefined) ? {} : this.state.s.measurement}/>
</Grid>
<Grid item xs={8}>
<DataProcessingPlots height={700} type={plot_type.INDEXING_RATE}/>
</Grid>
<Grid item xs={4}>
<DataProcessingSettings s={this.state.s.data_processing_settings} update={this.getValues}/>
</Grid>
{
this.renderTitleWithSwitch("Live image preview", this.state.show_preview, this.showPreviewToggle)
}
<Grid item xs={12}>
{this.state.show_preview ? <PreviewImage measuring={this.isMeasuring()}
max_image_number={this.state.s.buffer?.max_image_number}
min_image_number={this.state.s.buffer?.min_image_number}/> : ""}
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("Data collection",
this.state.show_data_collection, this.showDataCollectionToggle)
}
<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 ? <Stack spacing={2}>
<DetectorSettings s={this.state.s.detector_settings}/>
<PixelMask s={this.state.s.pixel_mask}/>
<FileWriterSettings s={this.state.s.file_writer_settings}/>
</Stack>: ""}
</Grid>
<Grid item xs={4}>
{this.state.show_detector_setup ?
<Stack spacing={2}>
<DetectorSelection s={this.state.s.detector_list}/>
<DetectorStatus s={this.state.s.detector}/>
<ZeroMQPreview s={this.state.s.zeromq_preview}/>
<IndexingSettings s={this.state.s.indexing} status={this.state.s.broker}/>
</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}/>
<AzIntSettings s={this.state.s.az_int}/>
</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)",
this.state.show_roi_setup, this.showROISetupToggle)
}
<Grid item xs={12}>
{this.state.show_roi_setup ? <ROI s={this.state.s.roi}/> : ""}
</Grid>
<br/><br/>
{
this.renderTitleWithSwitch("FPGA status",
this.state.show_fpga_status, this.showFPGAStatusToggle)
}
<Grid item xs={12}>
{this.state.show_fpga_status ? <FpgaStatus s={this.state.s.fpga}/> : ""}
</Grid>
</Grid>
</div>
<br/>
<center>Developed at Paul Scherrer Institute (2019-2024). Main author: <a
href="mailto:filip.leonarski@psi.ch">Filip Leonarski</a> <br/>
For more information see <a href="https://doi.org/10.1107/S1600577522010268"><i>J. Synchrotron
Rad.</i> (2023). <b>30</b>, 227234</a> <br/>
Version: {JFJOCH_VERSION}&nbsp;&nbsp;&nbsp;
<a href="/frontend/openapi.html">API reference</a></center>
<br/>
</ThemeProvider>
}
}
export default App;