Skip to content

Commit f85bc17

Browse files
authored
Merge pull request #76 from DiamondLightSource/14_11-add-extruder
Add page for extruder collection
2 parents 56f9214 + 93d53cb commit f85bc17

18 files changed

+797
-502
lines changed

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Switch, Route } from "react-router-dom";
55
import { BeamlineI24 } from "./routes/BeamlineI24";
66
import { FixedTarget } from "./routes/FixedTarget";
77
import { SerialNavBar } from "./components/SerialNavBar";
8+
import { Extruder } from "./routes/Extruder";
89

910
function App() {
1011
const theme = useTheme();
@@ -27,6 +28,9 @@ function App() {
2728
<Route path="/fixed-target">
2829
<FixedTarget />
2930
</Route>
31+
<Route path="/extruder">
32+
<Extruder />
33+
</Route>
3034
</Switch>
3135
<Footer
3236
logo={theme.logos?.short}

src/blueapi/BlueapiComponents.tsx

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import {
88
Tooltip,
99
Typography,
1010
} from "@mui/material";
11-
import { forceString, ReadPvRawValue } from "../pv/util";
12-
import { RawValue } from "../pv/types";
11+
import { parseInstrumentSession, readVisitFromPv } from "./visit";
1312

1413
type SeverityLevel = "success" | "info" | "warning" | "error";
1514
type VariantChoice = "outlined" | "contained";
@@ -37,43 +36,6 @@ type RunPlanButtonProps = {
3736
// This will be another PR
3837
// See https://github.com/DiamondLightSource/mx-daq-ui/issues/71
3938

40-
/**
41-
* Read the full visit path from the visit PV set by the beamline staff.
42-
* @returns {string} the full visit pV /dls/i24/data/{year}/{visit}
43-
*/
44-
export function readVisitFromPv(): string {
45-
const fullVisitPath: RawValue = ReadPvRawValue({
46-
label: "visit",
47-
pv: "ca://BL24I-MO-IOC-13:GP100",
48-
});
49-
const visitString: string = forceString(fullVisitPath);
50-
return visitString;
51-
}
52-
53-
/**
54-
* Parse the full visit path and return only the instrument session.
55-
* An error will be raised if the instrument session value is undefined or
56-
* if the PV is not connected.
57-
* @param {string} visit The full visit path
58-
* @returns {string} Only the instrument session part of the visit path
59-
*/
60-
export function parseInstrumentSession(visit: string): string {
61-
let instrumentSession: string | undefined;
62-
if (visit === "not connected" || visit === "undefined") {
63-
const msg =
64-
"Unable to run plan as instrument session not set. Please check visit PV.";
65-
throw new Error(msg);
66-
} else {
67-
instrumentSession = visit.split("/").filter(Boolean).at(-1);
68-
if (!instrumentSession) {
69-
throw new Error(
70-
"Unable to run plan as something appears to be wrong with visit path"
71-
);
72-
}
73-
}
74-
return instrumentSession;
75-
}
76-
7739
export function RunPlanButton(props: RunPlanButtonProps) {
7840
const [openSnackbar, setOpenSnackbar] = React.useState<boolean>(false);
7941
const [msg, setMsg] = React.useState<string>("Running plan...");

src/blueapi/visit.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { RawValue } from "../pv/types";
2+
import { forceString, ReadPvRawValue } from "../pv/util";
3+
4+
/**
5+
* Read the full visit path from the visit PV set by the beamline staff.
6+
* @returns {string} the full visit pV /dls/i24/data/{year}/{visit}
7+
*/
8+
export function readVisitFromPv(): string {
9+
const fullVisitPath: RawValue = ReadPvRawValue({
10+
label: "visit",
11+
pv: "ca://BL24I-MO-IOC-13:GP100",
12+
});
13+
const visitString: string = forceString(fullVisitPath);
14+
return visitString;
15+
}
16+
17+
/**
18+
* Parse the full visit path and return only the instrument session.
19+
* An error will be raised if the instrument session value is undefined or
20+
* if the PV is not connected.
21+
* @param {string} visit The full visit path
22+
* @returns {string} Only the instrument session part of the visit path
23+
*/
24+
export function parseInstrumentSession(visit: string): string {
25+
let instrumentSession: string | undefined;
26+
if (visit === "not connected" || visit === "undefined") {
27+
const msg =
28+
"Unable to run plan as instrument session not set. Please check visit PV.";
29+
throw new Error(msg);
30+
} else {
31+
instrumentSession = visit.split("/").filter(Boolean).at(-1);
32+
if (!instrumentSession) {
33+
throw new Error(
34+
"Unable to run plan as something appears to be wrong with visit path"
35+
);
36+
}
37+
}
38+
return instrumentSession;
39+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { Box, Grid2, Stack } from "@mui/material";
2+
import React from "react";
3+
import { ParameterInput } from "../ParameterInputs";
4+
import {
5+
LaserCheckButtons,
6+
PumpProbeSelection,
7+
PumpProbeSetup,
8+
} from "./PumpProbeSelection";
9+
import { AbortButton, RunPlanButton } from "../../blueapi/BlueapiComponents";
10+
11+
/**Main collection input window for the extruderpanel. */
12+
export function CollectionSetupEx() {
13+
const [subDir, setSubDir] = React.useState<string>("path/to/dir");
14+
const [fileName, setFileName] = React.useState<string>("test");
15+
const [expTime, setExpTime] = React.useState<number>(0.01);
16+
const [numImages, setNumImages] = React.useState<number>(1);
17+
const [trans, setTrans] = React.useState<number>(0.3);
18+
const [detDist, setDetDist] = React.useState<number>(1350);
19+
const [pumpProbe, setPumpProbe] = React.useState<boolean>(false);
20+
const [laserDwell, setLaserDwell] = React.useState<number>(0);
21+
const [laserDelay, setLaserDelay] = React.useState<number>(0);
22+
23+
return (
24+
<Box sx={{ flexGrow: 1, marginRight: 10, marginLeft: 10 }}>
25+
<Grid2 container spacing={2}>
26+
<Grid2 size={4.5}>
27+
<Stack direction={"column"} spacing={1} alignItems={"center"}>
28+
<ParameterInput
29+
value={subDir}
30+
onSet={setSubDir}
31+
label="Sub-directory"
32+
tooltip="Location inside visit directory to save data"
33+
/>
34+
<ParameterInput
35+
value={fileName}
36+
onSet={setFileName}
37+
label="File Name"
38+
tooltip="Filename prefix."
39+
/>
40+
<ParameterInput
41+
value={numImages}
42+
onSet={setNumImages}
43+
label="Number of images"
44+
tooltip="How many images should be collected"
45+
/>
46+
<ParameterInput
47+
value={expTime}
48+
onSet={setExpTime}
49+
label="Exposure Time (s)"
50+
tooltip="Exposure time for each window, in seconds"
51+
/>
52+
<ParameterInput
53+
value={trans}
54+
onSet={setTrans}
55+
label="Transmission (fraction)"
56+
tooltip="Request transmission for collection, expressed as a fraction"
57+
/>
58+
<ParameterInput
59+
value={detDist}
60+
onSet={setDetDist}
61+
label="Detector Distance (mm)"
62+
tooltip="Distance to move the detector y stage to, in millimeters"
63+
/>
64+
</Stack>
65+
</Grid2>
66+
<Grid2 size={3}>
67+
<Stack direction={"column"} spacing={1} alignItems={"center"}>
68+
<PumpProbeSelection
69+
pumpProbe={pumpProbe}
70+
setPumpProbe={setPumpProbe}
71+
/>
72+
<PumpProbeSetup
73+
dwell={laserDwell}
74+
delay={laserDelay}
75+
render={pumpProbe}
76+
setDwell={setLaserDwell}
77+
setDelay={setLaserDelay}
78+
/>
79+
<LaserCheckButtons />
80+
</Stack>
81+
</Grid2>
82+
<Grid2 size={4.5}>
83+
<Stack direction={"column"} spacing={1} alignItems={"center"}>
84+
<RunPlanButton
85+
btnLabel="Initialise on Start"
86+
planName="initialise_extruder"
87+
title="Initialise parameters for extruder"
88+
btnSize="large"
89+
/>
90+
<RunPlanButton
91+
btnLabel="Enter hutch"
92+
planName="enter_hutch"
93+
title="Move detector stage before entering hutch"
94+
btnSize="large"
95+
/>
96+
</Stack>
97+
</Grid2>
98+
<Grid2 size={12}>
99+
<Stack direction={"row"} spacing={8} justifyContent={"center"}>
100+
<RunPlanButton
101+
btnLabel="Start!"
102+
planName="gui_run_extruder_collection"
103+
planParams={{
104+
sub_dir: subDir,
105+
file_name: fileName,
106+
exp_time: expTime,
107+
det_dist: detDist,
108+
transmission: trans,
109+
num_images: numImages,
110+
pump_probe: pumpProbe,
111+
laser_dwell: laserDwell,
112+
laser_delay: laserDelay,
113+
}}
114+
title="Start extruder collection"
115+
btnSize="large"
116+
/>
117+
<AbortButton />
118+
</Stack>
119+
</Grid2>
120+
</Grid2>
121+
</Box>
122+
);
123+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import {
2+
FormControl,
3+
InputLabel,
4+
MenuItem,
5+
Select,
6+
Tooltip,
7+
} from "@mui/material";
8+
import { ParameterInput } from "../ParameterInputs";
9+
import React from "react";
10+
import { RunPlanButton } from "../../blueapi/BlueapiComponents";
11+
12+
export function PumpProbeSelection({
13+
pumpProbe,
14+
setPumpProbe,
15+
}: {
16+
pumpProbe: boolean;
17+
setPumpProbe: React.Dispatch<React.SetStateAction<boolean>>;
18+
}) {
19+
const handleChange = (choice: string) => {
20+
let newValue: boolean;
21+
if (choice.toLowerCase() === "true") {
22+
newValue = true;
23+
} else {
24+
newValue = false;
25+
}
26+
setPumpProbe(newValue);
27+
};
28+
return (
29+
<Tooltip title="Is this a pump probe experiment?" placement="right">
30+
<FormControl size="small" style={{ width: 180 }}>
31+
<InputLabel id="pp-ex">Pump Probe</InputLabel>
32+
<Select
33+
labelId="pp-ex"
34+
id="pp"
35+
value={String(pumpProbe)}
36+
label="Pump Probe"
37+
onChange={(e) => handleChange(e.target.value)}
38+
>
39+
<MenuItem value={"true"}>True</MenuItem>
40+
<MenuItem value={"false"}>False</MenuItem>
41+
</Select>
42+
</FormControl>
43+
</Tooltip>
44+
);
45+
}
46+
47+
export function PumpProbeSetup({
48+
dwell,
49+
delay,
50+
render,
51+
setDwell,
52+
setDelay,
53+
}: {
54+
dwell: number;
55+
delay: number;
56+
render: boolean;
57+
setDwell: React.Dispatch<React.SetStateAction<number>>;
58+
setDelay: React.Dispatch<React.SetStateAction<number>>;
59+
}): JSX.Element | null {
60+
if (render === false) {
61+
return null;
62+
} else {
63+
return (
64+
<React.Fragment>
65+
<ParameterInput
66+
value={dwell}
67+
onSet={setDwell}
68+
label="Laser Dwell (s)"
69+
tooltip="Exposure time for the laser pump, in seconds"
70+
/>
71+
<ParameterInput
72+
value={delay}
73+
onSet={setDelay}
74+
label="Laser Delay (s)"
75+
tooltip="Delay time between the laser pump and the collection, in seconds"
76+
/>
77+
</React.Fragment>
78+
);
79+
}
80+
}
81+
82+
export function LaserCheckButtons() {
83+
return (
84+
<React.Fragment>
85+
<RunPlanButton
86+
btnLabel="Laser ON"
87+
planName="laser_check"
88+
planParams={{ mode: "laseron" }}
89+
title="Open shutter and check laser beam"
90+
btnSize="small"
91+
/>
92+
<RunPlanButton
93+
btnLabel="Laser OFF"
94+
planName="laser_check"
95+
planParams={{ mode: "laseroff" }}
96+
title="Switch off laser beam"
97+
btnSize="small"
98+
/>
99+
</React.Fragment>
100+
);
101+
}

0 commit comments

Comments
 (0)