Skip to content

Commit 7efb06e

Browse files
committed
Merge branch 'main' into 12-add-scan-pattern-selection-dropdown-to-replace-scatter-checkbox
2 parents c762fa9 + c50f40a commit 7efb06e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1199
-596
lines changed

.github/workflows/gh-pages.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,27 @@ jobs:
1515

1616
steps:
1717
- name: Checkout
18-
uses: actions/checkout@v4
18+
uses: actions/checkout@v5
1919

2020
- name: Set up Python
21-
uses: actions/setup-python@v5
21+
uses: actions/setup-python@v6
2222
with:
2323
python-version: "3.13"
2424

2525
- name: Install uv
26+
uses: astral-sh/setup-uv@v7
27+
28+
- uses: webfactory/ssh-agent@v0.9.0
29+
with:
30+
ssh-private-key: |
31+
${{ secrets.GITLAB_TIQI_ZEDBOARD_SSH_KEY }}
32+
33+
- name: Configure SSH for GitLab
34+
env:
35+
SSH_KEY: ${{ secrets.GITLAB_TIQI_ZEDBOARD_SSH_KEY }}
2636
run: |
27-
curl -fsSL https://astral.sh/uv/install.sh | sh
28-
echo "$HOME/.local/bin" >> $GITHUB_PATH
37+
mkdir -p ~/.ssh && chmod 700 ~/.ssh
38+
ssh-keyscan gitlab.phys.ethz.ch >> ~/.ssh/known_hosts
2939
3040
- name: Sync build dependencies
3141
run: uv sync --no-dev --group docs

.github/workflows/release.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ jobs:
4141
openssh-client git ca-certificates curl binutils gh
4242
4343
- name: Install uv
44-
run: |
45-
curl -fsSL https://astral.sh/uv/install.sh | sh
46-
echo "$HOME/.local/bin" >> $GITHUB_PATH
44+
uses: astral-sh/setup-uv@v7
4745

4846
- uses: webfactory/ssh-agent@v0.9.0
4947
with:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ If you prefer to run ICON from source, clone the repository and use [`uv`](https
5656
```bash
5757
git clone https://github.com/tiqi-group/icon.git
5858
cd icon
59-
uv sync --extras server
59+
uv sync --extra server --extra zedboard
6060
uv run python -m icon.server
6161
```
6262
<!--getting-started-end-->
@@ -87,7 +87,7 @@ The web frontend is served automatically by the ICON backend. By default it is a
8787
Set up the development environment:
8888

8989
```bash
90-
uv sync --all-extras --dev
90+
uv sync --all-extras --group dev
9191
```
9292

9393
Start a development InfluxDB instance:

docs/getting-started/running-icon.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@
44
end="<!--getting-started-end-->"
55
heading-offset=-1
66
%}
7+
8+
## Ionpulse
9+
To be able to run experiments, ICON must connect to Ionpulse, the server application running on the control system such QuENCH RFSoC, QuENCH MicroTCA or M-ACTION. Configure the URL or IP and port under Settings -> Hardware.
10+
11+
### Development
12+
If you are testing/developing ICON without the control system, you can use the ionpulse emulator.
13+
See the [Ionpulse sw test README](https://gitlab.phys.ethz.ch/tiqi-projects/ionpulse_sw_test/-/blob/master/README.md) for more info on how to set up the emulator.

frontend/src/components/ExperimentDetails.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const ExperimentDetails = ({ experimentKey }: { experimentKey: string }) => {
4242
<ParameterGroupDisplay
4343
experimentKey={experimentKey}
4444
experimentGroup={group}
45+
parameters={experiments[experimentKey]?.parameters?.[group] || {}}
4546
/>
4647
</AccordionDetails>
4748
</Accordion>

frontend/src/components/JobView.tsx

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect, useState } from "react";
12
import {
23
Button,
34
Card,
@@ -7,22 +8,23 @@ import {
78
IconButton,
89
Switch,
910
Tooltip,
11+
Divider,
1012
} from "@mui/material";
11-
import { useExperimentData } from "../hooks/useExperimentData";
13+
import { ExpandLess, ExpandMore } from "@mui/icons-material";
1214
import ResultChannelPlot from "../components/ResultChannelPlot";
13-
import { useEffect, useState } from "react";
14-
import { ExperimentMetadata } from "../types/ExperimentMetadata";
15-
import { runMethod } from "../socket";
16-
import { deserialize } from "../utils/deserializer";
17-
import { SerializedObject } from "../types/SerializedObject";
1815
import { JobStatusIndicator } from "../components/JobStatusIndicator";
19-
import { useJobInfo } from "../hooks/useJobInfo";
16+
import { ParameterGroupDisplay } from "../components/ParameterGroupDisplay";
17+
import { useExperimentData } from "../hooks/useExperimentData";
2018
import { useJobRunInfo } from "../hooks/useJobRunInfo";
21-
import { cancelJob } from "../utils/cancelJob";
19+
import { useJobInfo } from "../hooks/useJobInfo";
20+
import { runMethod } from "../socket";
21+
import { ExperimentMetadata } from "../types/ExperimentMetadata";
22+
import { SerializedObject } from "../types/SerializedObject";
2223
import { JobStatus } from "../types/enums";
24+
import { deserialize } from "../utils/deserializer";
2325
import { updateJobParams } from "../utils/updateJobParams";
26+
import { cancelJob } from "../utils/cancelJob";
2427
import HistogramPlot from "./jobView/HistogramPlot";
25-
import { ExpandLess, ExpandMore } from "@mui/icons-material";
2628

2729
function getPlotTitle(scheduledTime?: string, experimentName?: string): string {
2830
if (!scheduledTime) return experimentName || "";
@@ -104,13 +106,16 @@ export const JobView = ({
104106

105107
useEffect(() => {
106108
if (jobInfo?.experiment_source.experiment_id)
107-
runMethod("experiments.get_experiments", [], {}, (ack) => {
108-
setExperimentMetadata(
109-
deserialize(ack as SerializedObject)[
110-
jobInfo?.experiment_source.experiment_id
111-
] as ExperimentMetadata,
112-
);
113-
});
109+
runMethod(
110+
"experiments.get_metadata",
111+
[jobInfo?.experiment_source.experiment_id],
112+
{},
113+
(ack) => {
114+
setExperimentMetadata(
115+
deserialize(ack as SerializedObject) as ExperimentMetadata,
116+
);
117+
},
118+
);
114119
}, [jobInfo]);
115120

116121
useEffect(() => {
@@ -268,8 +273,24 @@ export const JobView = ({
268273
<Grid size={{ xs: 12 }}>
269274
<Card>
270275
<CardContent>
271-
<div style={{ display: "flex" }}>
276+
<div style={{ display: "flex", flexDirection: "column" }}>
272277
<Typography variant="h6">Parameter Values</Typography>
278+
{Object.entries(experimentMetadata?.parameters || {}).map(
279+
([displayGroup, parameters], index) => (
280+
<div key={displayGroup}>
281+
<Typography variant="h6">{displayGroup}</Typography>
282+
<ParameterGroupDisplay
283+
displayGroup={displayGroup}
284+
parameters={parameters}
285+
values={experimentData.parameters}
286+
readOnly={true}
287+
/>
288+
{index <
289+
Object.keys(experimentMetadata?.parameters || {}).length -
290+
1 && <Divider sx={{ pt: 2 }} />}
291+
</div>
292+
),
293+
)}
273294
<div style={{ flexGrow: 1, alignContent: "center" }} />
274295
<Button
275296
variant="outlined"

frontend/src/components/ParameterGroupDisplay.tsx

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
import { useContext, useMemo } from "react";
2-
import { ExperimentsContext } from "../contexts/ExperimentsContext";
3-
import { ParameterDisplayGroupsContext } from "../contexts/ParameterDisplayGroupsContext";
1+
import { useMemo } from "react";
42
import { ButtonComponent } from "./parameterComponents/Button";
3+
import { Output } from "./parameterComponents/Output";
54
import { ParameterNumberComponent } from "./parameterComponents/ParameterNumberComponent";
65
import { Combobox } from "./parameterComponents/Combobox";
76
import { useScanContext } from "../hooks/useScanContext";
87
import { getScanIndex } from "../utils/getScanIndex";
98
import { useResponsiveGridColumns } from "../hooks/useResponsiveGridColumns";
9+
import { ParameterMetadata } from "../types/ExperimentMetadata";
10+
import { ParameterValue } from "../types/ExperimentData";
1011

1112
interface ParameterGroupDisplayProps {
13+
parameters: Record<string, ParameterMetadata>;
14+
values?: Record<string, ParameterValue>;
1215
experimentKey?: string;
1316
experimentGroup?: string;
1417
namespace?: string;
1518
displayGroup?: string;
19+
readOnly?: boolean;
1620
}
1721

1822
const extractNamespaceFromParamId = (parameterId: string): string | null => {
@@ -25,33 +29,13 @@ export const ParameterGroupDisplay = ({
2529
experimentGroup,
2630
namespace,
2731
displayGroup,
32+
parameters,
33+
values,
34+
readOnly = false,
2835
}: ParameterGroupDisplayProps) => {
2936
const { scannedParamKeys, handleRightClick } = useScanContext();
3037
const gridTemplateColumns = useResponsiveGridColumns();
3138

32-
const experiments = useContext(ExperimentsContext);
33-
const { parameterDisplayGroups } = useContext(ParameterDisplayGroupsContext);
34-
35-
// Determine parameters based on props
36-
const parameters = useMemo(() => {
37-
if (experimentKey && experimentGroup) {
38-
// Fetch parameters from ExperimentsContext
39-
return experiments[experimentKey]?.parameters?.[experimentGroup] || {};
40-
}
41-
if (namespace && displayGroup) {
42-
// Fetch parameters from ParameterDisplayGroupsContext
43-
return parameterDisplayGroups[`${namespace} (${displayGroup})`] || {};
44-
}
45-
return {};
46-
}, [
47-
experimentKey,
48-
experimentGroup,
49-
namespace,
50-
displayGroup,
51-
experiments,
52-
parameterDisplayGroups,
53-
]);
54-
5539
// Memoize sorting
5640
const sortedParameters = useMemo(() => {
5741
return Object.entries(parameters).sort((a, b) =>
@@ -69,6 +53,20 @@ export const ParameterGroupDisplay = ({
6953
>
7054
{sortedParameters.map(([paramId, paramMetadata]) => {
7155
const scanIndex = getScanIndex(paramId, scannedParamKeys);
56+
const value = values?.[paramId]?.value;
57+
58+
if (readOnly) {
59+
return (
60+
<Output
61+
id={paramId}
62+
label={paramMetadata.display_name}
63+
value={value}
64+
defaultValue={paramMetadata.default_value}
65+
scanIndex={scanIndex}
66+
description={paramId}
67+
/>
68+
);
69+
}
7270

7371
if (paramId.includes("param_type='ParameterTypes.BOOLEAN'")) {
7472
return (
@@ -79,6 +77,7 @@ export const ParameterGroupDisplay = ({
7977
id={paramId}
8078
displayName={paramMetadata.display_name}
8179
defaultValue={Boolean(paramMetadata.default_value)}
80+
value={value != null ? Boolean(value) : undefined}
8281
namespace={
8382
namespace === undefined
8483
? experimentKey === undefined
@@ -101,6 +100,7 @@ export const ParameterGroupDisplay = ({
101100
key={paramId}
102101
id={paramId}
103102
defaultValue={String(paramMetadata.default_value)}
103+
value={value?.toString()}
104104
displayName={paramMetadata.display_name}
105105
allowedValues={paramMetadata.allowed_values!}
106106
/>
@@ -117,6 +117,7 @@ export const ParameterGroupDisplay = ({
117117
min={paramMetadata?.min_value}
118118
max={paramMetadata?.max_value}
119119
unit={paramMetadata?.unit}
120+
value={value?.toString()}
120121
namespace={
121122
namespace === undefined
122123
? experimentKey === undefined

0 commit comments

Comments
 (0)