qsharp-lang 1.0.32-dev → 1.0.34-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/katas-content.generated.js +17 -17
- package/dist/log.js +2 -3
- package/dist/ux/ticks.d.ts +6 -0
- package/dist/ux/ticks.js +125 -0
- package/lib/node/qsc_wasm.cjs +85 -92
- package/lib/node/qsc_wasm.d.cts +1 -1
- package/lib/node/qsc_wasm_bg.wasm +0 -0
- package/lib/web/qsc_wasm.d.ts +1 -1
- package/lib/web/qsc_wasm.js +80 -90
- package/lib/web/qsc_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/ux/colormap.ts +51 -0
- package/ux/data.ts +68 -0
- package/ux/estimatesOverview.tsx +238 -0
- package/ux/generate_report_code.py +243 -0
- package/ux/index.ts +4 -2
- package/ux/output_data.md +537 -0
- package/ux/qsharp-ux.css +37 -0
- package/ux/reTable.tsx +7 -28
- package/ux/report.ts +591 -0
- package/ux/resultsTable.tsx +35 -49
- package/ux/scatterChart.tsx +369 -0
- package/ux/spaceChart.tsx +2 -2
package/ux/resultsTable.tsx
CHANGED
|
@@ -2,44 +2,48 @@
|
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
3
|
|
|
4
4
|
import { useRef, useState } from "preact/hooks";
|
|
5
|
-
import { type ReData } from "./reTable.js";
|
|
6
5
|
|
|
7
|
-
type CellValue = string | number | { value: string; sortBy: number };
|
|
6
|
+
export type CellValue = string | number | { value: string; sortBy: number };
|
|
7
|
+
export type Row = {
|
|
8
|
+
color: string;
|
|
9
|
+
cells: CellValue[];
|
|
10
|
+
};
|
|
8
11
|
|
|
9
12
|
// Note: column 0 is expected to be unique amongst all rows
|
|
10
13
|
export function ResultsTable(props: {
|
|
11
14
|
columnNames: string[];
|
|
12
|
-
|
|
15
|
+
rows: Row[];
|
|
13
16
|
initialColumns: number[];
|
|
14
17
|
ensureSelected: boolean;
|
|
15
|
-
onRowSelected(rowId: string): void;
|
|
16
18
|
onRowDeleted(rowId: string): void;
|
|
19
|
+
selectedRow: string | null; // type selected to confirm with the useState pattern on the parent component
|
|
20
|
+
setSelectedRow(rowId: string): void;
|
|
17
21
|
}) {
|
|
18
22
|
const [showColumns, setShowColumns] = useState(props.initialColumns);
|
|
19
23
|
const [sortColumn, setSortColumn] = useState<{
|
|
20
24
|
columnId: number;
|
|
21
25
|
ascending: boolean;
|
|
22
26
|
} | null>(null);
|
|
23
|
-
|
|
27
|
+
|
|
24
28
|
const [showColumnMenu, setShowColumnMenu] = useState(false);
|
|
25
29
|
const [showRowMenu, setShowRowMenu] = useState("");
|
|
26
30
|
|
|
27
|
-
const rows = props.data.map(ReDataToRow);
|
|
28
|
-
|
|
29
31
|
// Find the first row that is new in the current sort order
|
|
30
|
-
const newest = getSortedRows(rows).find(
|
|
31
|
-
(row) => (row[row.length - 1] as string) === "New",
|
|
32
|
+
const newest = getSortedRows(props.rows).find(
|
|
33
|
+
(row) => (row.cells[row.cells.length - 1] as string) === "New",
|
|
32
34
|
);
|
|
33
35
|
|
|
34
36
|
// Select the first of the newest rows, otherwise preserve the existing selection
|
|
35
37
|
if (newest && props.ensureSelected) {
|
|
36
|
-
const rowId = newest[0].toString();
|
|
38
|
+
const rowId = newest.cells[0].toString();
|
|
37
39
|
setSelectedRow(rowId);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
} else if (
|
|
41
|
+
!props.selectedRow &&
|
|
42
|
+
props.ensureSelected &&
|
|
43
|
+
props.rows.length > 0
|
|
44
|
+
) {
|
|
45
|
+
const rowId = props.rows[0].cells[0].toString();
|
|
41
46
|
setSelectedRow(rowId);
|
|
42
|
-
props.onRowSelected(rowId);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
// Use to track the column being dragged
|
|
@@ -79,6 +83,10 @@ export function ResultsTable(props: {
|
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
function setSelectedRow(rowId: string) {
|
|
87
|
+
props.setSelectedRow(rowId);
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
function onDragOver(ev: DragEvent) {
|
|
83
91
|
if (!(ev.target instanceof HTMLElement)) return;
|
|
84
92
|
const thisColId = ev.target.closest("th")?.dataset["colid"];
|
|
@@ -156,7 +164,7 @@ export function ResultsTable(props: {
|
|
|
156
164
|
}
|
|
157
165
|
}
|
|
158
166
|
|
|
159
|
-
function getSortedRows(rows:
|
|
167
|
+
function getSortedRows(rows: Row[]) {
|
|
160
168
|
if (!sortColumn) return rows;
|
|
161
169
|
|
|
162
170
|
const colIdx = sortColumn.columnId;
|
|
@@ -164,8 +172,8 @@ export function ResultsTable(props: {
|
|
|
164
172
|
|
|
165
173
|
const sortedRows = [...rows];
|
|
166
174
|
sortedRows.sort((a, b) => {
|
|
167
|
-
const aVal = a[colIdx];
|
|
168
|
-
const bVal = b[colIdx];
|
|
175
|
+
const aVal = a.cells[colIdx];
|
|
176
|
+
const bVal = b.cells[colIdx];
|
|
169
177
|
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
170
178
|
return ascending ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
|
|
171
179
|
} else if (typeof aVal === "number" && typeof bVal === "number") {
|
|
@@ -193,11 +201,10 @@ export function ResultsTable(props: {
|
|
|
193
201
|
}
|
|
194
202
|
|
|
195
203
|
function rowClicked(rowId: string) {
|
|
196
|
-
if (selectedRow === rowId && props.ensureSelected) return;
|
|
204
|
+
if (props.selectedRow === rowId && props.ensureSelected) return;
|
|
197
205
|
|
|
198
|
-
const newSelectedRow = selectedRow === rowId ? "" : rowId;
|
|
206
|
+
const newSelectedRow = props.selectedRow === rowId ? "" : rowId;
|
|
199
207
|
setSelectedRow(newSelectedRow);
|
|
200
|
-
props.onRowSelected(newSelectedRow);
|
|
201
208
|
}
|
|
202
209
|
|
|
203
210
|
function onClickRowMenu(ev: MouseEvent, rowid: string) {
|
|
@@ -246,9 +253,8 @@ export function ResultsTable(props: {
|
|
|
246
253
|
e.stopPropagation();
|
|
247
254
|
// Clear out any menus or selections for the row if needed
|
|
248
255
|
setShowRowMenu("");
|
|
249
|
-
if (selectedRow === rowId) {
|
|
256
|
+
if (props.selectedRow === rowId) {
|
|
250
257
|
setSelectedRow("");
|
|
251
|
-
props.onRowSelected("");
|
|
252
258
|
}
|
|
253
259
|
props.onRowDeleted(rowId);
|
|
254
260
|
}
|
|
@@ -344,14 +350,14 @@ export function ResultsTable(props: {
|
|
|
344
350
|
</tr>
|
|
345
351
|
</thead>
|
|
346
352
|
<tbody>
|
|
347
|
-
{getSortedRows(rows).map((row) => {
|
|
348
|
-
const rowId = row[0].toString();
|
|
353
|
+
{getSortedRows(props.rows).map((row) => {
|
|
354
|
+
const rowId = row.cells[0].toString();
|
|
349
355
|
return (
|
|
350
356
|
<tr
|
|
351
357
|
onClick={() => rowClicked(rowId)}
|
|
352
358
|
data-rowid={rowId}
|
|
353
359
|
class={
|
|
354
|
-
rowId === selectedRow
|
|
360
|
+
rowId === props.selectedRow
|
|
355
361
|
? "qs-resultsTable-sortedTableSelectedRow"
|
|
356
362
|
: undefined
|
|
357
363
|
}
|
|
@@ -364,7 +370,7 @@ export function ResultsTable(props: {
|
|
|
364
370
|
<svg width="16" height="16" style="position: relative;">
|
|
365
371
|
<path
|
|
366
372
|
stroke-width="1.5"
|
|
367
|
-
stroke=
|
|
373
|
+
stroke={row.color}
|
|
368
374
|
stroke-linecap="round"
|
|
369
375
|
d="M4,5 h8 M4,8 h8 M4,11 h8"
|
|
370
376
|
/>
|
|
@@ -386,7 +392,9 @@ export function ResultsTable(props: {
|
|
|
386
392
|
</td>
|
|
387
393
|
{showColumns.map((idx) => {
|
|
388
394
|
return (
|
|
389
|
-
<td data-colid={idx.toString()}>
|
|
395
|
+
<td data-colid={idx.toString()}>
|
|
396
|
+
{getCellStr(row.cells[idx])}
|
|
397
|
+
</td>
|
|
390
398
|
);
|
|
391
399
|
})}
|
|
392
400
|
</tr>
|
|
@@ -396,25 +404,3 @@ export function ResultsTable(props: {
|
|
|
396
404
|
</table>
|
|
397
405
|
);
|
|
398
406
|
}
|
|
399
|
-
|
|
400
|
-
function ReDataToRow(data: ReData): CellValue[] {
|
|
401
|
-
return [
|
|
402
|
-
data.jobParams.runName,
|
|
403
|
-
data.jobParams.qubitParams.name,
|
|
404
|
-
data.jobParams.qecScheme.name,
|
|
405
|
-
data.jobParams.errorBudget,
|
|
406
|
-
data.physicalCounts.breakdown.algorithmicLogicalQubits,
|
|
407
|
-
data.physicalCounts.breakdown.algorithmicLogicalDepth,
|
|
408
|
-
data.logicalQubit.codeDistance,
|
|
409
|
-
data.physicalCounts.breakdown.numTstates,
|
|
410
|
-
data.physicalCounts.breakdown.numTfactories,
|
|
411
|
-
data.physicalCountsFormatted.physicalQubitsForTfactoriesPercentage,
|
|
412
|
-
{
|
|
413
|
-
value: data.physicalCountsFormatted.runtime,
|
|
414
|
-
sortBy: data.physicalCounts.runtime,
|
|
415
|
-
},
|
|
416
|
-
data.physicalCounts.rqops,
|
|
417
|
-
data.physicalCounts.physicalQubits,
|
|
418
|
-
data.new ? "New" : "Cached",
|
|
419
|
-
];
|
|
420
|
-
}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { CreateIntegerTicks, CreateTimeTicks, Tick } from "../src/ux/ticks.js";
|
|
5
|
+
|
|
6
|
+
export type ScatterSeries = {
|
|
7
|
+
color: string;
|
|
8
|
+
items: PlotItem[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type PlotItem = {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
label: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Axis = {
|
|
18
|
+
isTime: boolean;
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type Range = {
|
|
23
|
+
min: number;
|
|
24
|
+
max: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function HideTooltip() {
|
|
28
|
+
const tooltip = document.getElementById("tooltip");
|
|
29
|
+
if (tooltip) {
|
|
30
|
+
tooltip.setAttribute("visibility", "hidden");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function drawTooltip(target: SVGCircleElement, clicked: boolean = false) {
|
|
35
|
+
const xAttr = target.getAttribute("cx");
|
|
36
|
+
const x = xAttr ? parseInt(xAttr) : 0;
|
|
37
|
+
const yAttr = target.getAttribute("cy");
|
|
38
|
+
const y = yAttr ? parseInt(yAttr) : -0;
|
|
39
|
+
const text = target.getAttribute("data-label");
|
|
40
|
+
const tooltipTextLeftPadding = 5;
|
|
41
|
+
const tooltipRectanglePaddingHeight = 10;
|
|
42
|
+
const tooltipTextPaddingHeight = 25;
|
|
43
|
+
const tooltip = document.getElementById("tooltip");
|
|
44
|
+
const tooltipRect = document.getElementById("tooltipRect");
|
|
45
|
+
const tooltipText = document.getElementById(
|
|
46
|
+
"tooltipText",
|
|
47
|
+
) as unknown as SVGTextElement;
|
|
48
|
+
|
|
49
|
+
if (tooltipText) {
|
|
50
|
+
tooltipText.setAttribute("x", (x + tooltipTextLeftPadding).toString());
|
|
51
|
+
tooltipText.setAttribute("y", (y + tooltipTextPaddingHeight).toString());
|
|
52
|
+
tooltipText.textContent = text;
|
|
53
|
+
}
|
|
54
|
+
if (tooltipRect && tooltipText) {
|
|
55
|
+
const box = tooltipText.getBBox();
|
|
56
|
+
const textWidth = box.width;
|
|
57
|
+
tooltipRect.setAttribute(
|
|
58
|
+
"width",
|
|
59
|
+
(textWidth + 2 * tooltipTextLeftPadding).toString(),
|
|
60
|
+
);
|
|
61
|
+
tooltipRect.setAttribute("x", x.toString());
|
|
62
|
+
tooltipRect.setAttribute(
|
|
63
|
+
"y",
|
|
64
|
+
(y + tooltipRectanglePaddingHeight).toString(),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (tooltip) {
|
|
68
|
+
tooltip.setAttribute("visibility", "visible");
|
|
69
|
+
tooltip.setAttribute("clicked", clicked.toString());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function hideTooltipIfNotClicked() {
|
|
74
|
+
const tooltip = document.getElementById("tooltip");
|
|
75
|
+
if (tooltip) {
|
|
76
|
+
if (tooltip.getAttribute("clicked") === "false") {
|
|
77
|
+
tooltip.setAttribute("visibility", "hidden");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function deselectPoint() {
|
|
83
|
+
const chart = document.getElementById(`scatterChart`);
|
|
84
|
+
if (chart) {
|
|
85
|
+
if (chart.getAttribute("selectedPoint")) {
|
|
86
|
+
const point = document.getElementById(
|
|
87
|
+
chart.getAttribute("selectedPoint") as string,
|
|
88
|
+
);
|
|
89
|
+
if (point) {
|
|
90
|
+
point.classList.remove("qs-scatterChart-point-selected");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function SelectPoint(seriesIndex: number, pointIndex: number) {
|
|
97
|
+
deselectPoint();
|
|
98
|
+
const point = document.getElementById(`point-${seriesIndex}-${pointIndex}`);
|
|
99
|
+
const chart = document.getElementById(`scatterChart`);
|
|
100
|
+
if (point && chart) {
|
|
101
|
+
point.classList.add("qs-scatterChart-point-selected");
|
|
102
|
+
chart.setAttribute("selectedPoint", point.id);
|
|
103
|
+
drawTooltip(point as unknown as SVGCircleElement, true);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function ScatterChart(props: {
|
|
108
|
+
data: ScatterSeries[];
|
|
109
|
+
xAxis: Axis;
|
|
110
|
+
yAxis: Axis;
|
|
111
|
+
onPointSelected(seriesIndex: number, pointIndex: number): void;
|
|
112
|
+
}) {
|
|
113
|
+
const data = props.data;
|
|
114
|
+
|
|
115
|
+
function findMinMaxSingle(
|
|
116
|
+
series: ScatterSeries,
|
|
117
|
+
): [number, number, number, number] {
|
|
118
|
+
const xs = series.items.map((item) => item.x);
|
|
119
|
+
const ys = series.items.map((item) => item.y);
|
|
120
|
+
const minX = Math.min(...xs);
|
|
121
|
+
const maxX = Math.max(...xs);
|
|
122
|
+
const minY = Math.min(...ys);
|
|
123
|
+
const maxY = Math.max(...ys);
|
|
124
|
+
return [minX, maxX, minY, maxY];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function findMinMaxAll(
|
|
128
|
+
series: ScatterSeries[],
|
|
129
|
+
): [number, number, number, number] {
|
|
130
|
+
const minMax = series.map(findMinMaxSingle);
|
|
131
|
+
const minX = Math.min(...minMax.map((x) => x[0]));
|
|
132
|
+
const maxX = Math.max(...minMax.map((x) => x[1]));
|
|
133
|
+
const minY = Math.min(...minMax.map((x) => x[2]));
|
|
134
|
+
const maxY = Math.max(...minMax.map((x) => x[3]));
|
|
135
|
+
return [minX, maxX, minY, maxY];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const [minX, maxX, minY, maxY] = findMinMaxAll(data);
|
|
139
|
+
|
|
140
|
+
const rangeCoefficient = 2;
|
|
141
|
+
const rangeX: Range = {
|
|
142
|
+
min: minX / rangeCoefficient,
|
|
143
|
+
max: maxX * rangeCoefficient,
|
|
144
|
+
};
|
|
145
|
+
const rangeY: Range = {
|
|
146
|
+
min: minY / rangeCoefficient,
|
|
147
|
+
max: maxY * rangeCoefficient,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
function createAxisTicks(range: Range, isTime: boolean): Tick[] {
|
|
151
|
+
if (isTime) {
|
|
152
|
+
return CreateTimeTicks(range.min, range.max);
|
|
153
|
+
} else {
|
|
154
|
+
return CreateIntegerTicks(range.min, range.max);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const xTicks = createAxisTicks(rangeX, props.xAxis.isTime);
|
|
159
|
+
const yTicks = createAxisTicks(rangeY, props.yAxis.isTime);
|
|
160
|
+
|
|
161
|
+
function coordinateToSvgLogarithmic(
|
|
162
|
+
value: number,
|
|
163
|
+
range: Range,
|
|
164
|
+
size: number,
|
|
165
|
+
): number {
|
|
166
|
+
return (
|
|
167
|
+
((Math.log(value) - Math.log(range.min)) /
|
|
168
|
+
(Math.log(range.max) - Math.log(range.min))) *
|
|
169
|
+
size
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const yAxisTitleWidth = 20;
|
|
174
|
+
const yAxisTickCaptionMaxWidth = 100;
|
|
175
|
+
const axisTickLength = 5;
|
|
176
|
+
const axisLineWidth = 1;
|
|
177
|
+
const xLeftMargin =
|
|
178
|
+
yAxisTitleWidth + yAxisTickCaptionMaxWidth + axisTickLength + axisLineWidth;
|
|
179
|
+
const xRightMargin = 100; // to show tooltips on the right hand side. If we can move tooltips dynamicslly, we can get rid of this.
|
|
180
|
+
|
|
181
|
+
const axisTitleHeight = 20;
|
|
182
|
+
const xAxisTickCaptionMaxHeight = 16;
|
|
183
|
+
const yMargin =
|
|
184
|
+
axisTitleHeight +
|
|
185
|
+
xAxisTickCaptionMaxHeight +
|
|
186
|
+
axisTickLength +
|
|
187
|
+
axisLineWidth;
|
|
188
|
+
|
|
189
|
+
const svgWidth = 960;
|
|
190
|
+
const svgViewBoxWidthPadding = 50;
|
|
191
|
+
const svgHeight = 480;
|
|
192
|
+
const svgViewBoxHeightPadding = 10;
|
|
193
|
+
const svgXMin = -xLeftMargin;
|
|
194
|
+
|
|
195
|
+
const plotAreaWidth = svgWidth - xLeftMargin - xRightMargin;
|
|
196
|
+
const plotAreaHeight = svgHeight - yMargin;
|
|
197
|
+
|
|
198
|
+
const viewBox = `${svgXMin - svgViewBoxWidthPadding} ${
|
|
199
|
+
-plotAreaHeight - svgViewBoxHeightPadding
|
|
200
|
+
} ${svgWidth + svgViewBoxWidthPadding} ${
|
|
201
|
+
svgHeight + svgViewBoxHeightPadding
|
|
202
|
+
}`;
|
|
203
|
+
|
|
204
|
+
const yAxisTextPaddingFromTicks = 5;
|
|
205
|
+
const yAxisTextYPadding = 6;
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<div style="display: flex; flex-wrap: wrap; margin-top: 8px;">
|
|
209
|
+
<div class="chart-container">
|
|
210
|
+
<svg
|
|
211
|
+
width={svgWidth}
|
|
212
|
+
height={svgHeight}
|
|
213
|
+
viewBox={viewBox}
|
|
214
|
+
id="scatterChart"
|
|
215
|
+
>
|
|
216
|
+
<line
|
|
217
|
+
id="xAxis"
|
|
218
|
+
x1="0"
|
|
219
|
+
y1="0"
|
|
220
|
+
x2={plotAreaWidth}
|
|
221
|
+
y2="0"
|
|
222
|
+
stroke="var(--border-color)"
|
|
223
|
+
/>
|
|
224
|
+
|
|
225
|
+
{xTicks.map((tick) => {
|
|
226
|
+
const x = coordinateToSvgLogarithmic(
|
|
227
|
+
tick.value,
|
|
228
|
+
rangeX,
|
|
229
|
+
plotAreaWidth,
|
|
230
|
+
);
|
|
231
|
+
return (
|
|
232
|
+
<g>
|
|
233
|
+
<line
|
|
234
|
+
x1={x}
|
|
235
|
+
y1="1"
|
|
236
|
+
x2={x}
|
|
237
|
+
y2={axisTickLength}
|
|
238
|
+
stroke="var(--border-color)"
|
|
239
|
+
/>
|
|
240
|
+
<text
|
|
241
|
+
x={x}
|
|
242
|
+
y={axisTickLength + xAxisTickCaptionMaxHeight}
|
|
243
|
+
text-anchor="middle"
|
|
244
|
+
fill="var(--main-color)"
|
|
245
|
+
>
|
|
246
|
+
{tick.label}
|
|
247
|
+
</text>
|
|
248
|
+
</g>
|
|
249
|
+
);
|
|
250
|
+
})}
|
|
251
|
+
|
|
252
|
+
<line
|
|
253
|
+
id="yAxis"
|
|
254
|
+
x1="0"
|
|
255
|
+
y1="0"
|
|
256
|
+
x2="0"
|
|
257
|
+
y2={-svgHeight}
|
|
258
|
+
stroke="var(--border-color)"
|
|
259
|
+
/>
|
|
260
|
+
|
|
261
|
+
{yTicks.map((tick) => {
|
|
262
|
+
const y = -coordinateToSvgLogarithmic(
|
|
263
|
+
tick.value,
|
|
264
|
+
rangeY,
|
|
265
|
+
plotAreaHeight,
|
|
266
|
+
);
|
|
267
|
+
return (
|
|
268
|
+
<g>
|
|
269
|
+
<line
|
|
270
|
+
x1="0"
|
|
271
|
+
y1={y}
|
|
272
|
+
x2={-axisTickLength}
|
|
273
|
+
y2={y}
|
|
274
|
+
stroke="var(--border-color)"
|
|
275
|
+
/>
|
|
276
|
+
<text
|
|
277
|
+
x={-axisTickLength - yAxisTextPaddingFromTicks}
|
|
278
|
+
y={y + yAxisTextYPadding}
|
|
279
|
+
text-anchor="end"
|
|
280
|
+
fill="var(--main-color)"
|
|
281
|
+
>
|
|
282
|
+
{tick.label}
|
|
283
|
+
</text>
|
|
284
|
+
</g>
|
|
285
|
+
);
|
|
286
|
+
})}
|
|
287
|
+
|
|
288
|
+
<text
|
|
289
|
+
x={plotAreaWidth / 2}
|
|
290
|
+
y={yMargin}
|
|
291
|
+
class="qs-scatterChart-x-axisTitle"
|
|
292
|
+
>
|
|
293
|
+
{props.xAxis.label} (logarithmic)
|
|
294
|
+
</text>
|
|
295
|
+
|
|
296
|
+
<text
|
|
297
|
+
x={xLeftMargin - axisTitleHeight}
|
|
298
|
+
y={plotAreaHeight / 2}
|
|
299
|
+
class="qs-scatterChart-y-axisTitle"
|
|
300
|
+
>
|
|
301
|
+
{props.yAxis.label} (logarithmic)
|
|
302
|
+
</text>
|
|
303
|
+
|
|
304
|
+
<text
|
|
305
|
+
class="qs-scatterChart-watermark"
|
|
306
|
+
x={xLeftMargin - axisTitleHeight}
|
|
307
|
+
y={-svgHeight + yMargin}
|
|
308
|
+
>
|
|
309
|
+
Created with Azure Quantum Resource Estimator
|
|
310
|
+
</text>
|
|
311
|
+
|
|
312
|
+
{data.map((data, seriesIndex) => {
|
|
313
|
+
return data.items.map((item, pointIndex) => {
|
|
314
|
+
const x = coordinateToSvgLogarithmic(
|
|
315
|
+
item.x,
|
|
316
|
+
rangeX,
|
|
317
|
+
plotAreaWidth,
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
const y = -coordinateToSvgLogarithmic(
|
|
321
|
+
item.y,
|
|
322
|
+
rangeY,
|
|
323
|
+
plotAreaHeight,
|
|
324
|
+
);
|
|
325
|
+
return (
|
|
326
|
+
<circle
|
|
327
|
+
id={`point-${seriesIndex}-${pointIndex}`}
|
|
328
|
+
cx={x}
|
|
329
|
+
cy={y}
|
|
330
|
+
data-label={item.label}
|
|
331
|
+
class="qs-scatterChart-point"
|
|
332
|
+
stroke={data.color}
|
|
333
|
+
onMouseOver={(e) => {
|
|
334
|
+
drawTooltip(e.currentTarget, false);
|
|
335
|
+
deselectPoint();
|
|
336
|
+
}}
|
|
337
|
+
onClick={() => {
|
|
338
|
+
SelectPoint(seriesIndex, pointIndex);
|
|
339
|
+
props.onPointSelected(seriesIndex, pointIndex);
|
|
340
|
+
}}
|
|
341
|
+
onMouseOut={() => hideTooltipIfNotClicked()}
|
|
342
|
+
/>
|
|
343
|
+
);
|
|
344
|
+
});
|
|
345
|
+
})}
|
|
346
|
+
<g id="tooltip" visibility="hidden">
|
|
347
|
+
<rect
|
|
348
|
+
id="tooltipRect"
|
|
349
|
+
x="100"
|
|
350
|
+
y="-100"
|
|
351
|
+
width="200"
|
|
352
|
+
height="22"
|
|
353
|
+
fill="white"
|
|
354
|
+
stroke="black"
|
|
355
|
+
stroke-width="1"
|
|
356
|
+
/>
|
|
357
|
+
<text
|
|
358
|
+
id="tooltipText"
|
|
359
|
+
x="105"
|
|
360
|
+
y="115"
|
|
361
|
+
text-anchor="left"
|
|
362
|
+
fill="black"
|
|
363
|
+
></text>
|
|
364
|
+
</g>
|
|
365
|
+
</svg>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
);
|
|
369
|
+
}
|
package/ux/spaceChart.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { SingleEstimateResult } from "./data.js";
|
|
5
5
|
|
|
6
6
|
function getPieSegment(
|
|
7
7
|
x: number,
|
|
@@ -26,7 +26,7 @@ function getPieSegment(
|
|
|
26
26
|
return d;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function SpaceChart(props: { estimatesData:
|
|
29
|
+
export function SpaceChart(props: { estimatesData: SingleEstimateResult }) {
|
|
30
30
|
const breakdown = props.estimatesData.physicalCounts.breakdown;
|
|
31
31
|
|
|
32
32
|
// The values to be shown on the pie chart
|