Spaces:
Runtime error
Runtime error
harishaseebat92
commited on
Commit
·
6ca7a4a
1
Parent(s):
b112afa
EM : IBM/ION Job Retrieve Upload Window
Browse files- em/simulation.py +133 -105
- em/state.py +1 -2
- em/ui.py +102 -75
- qlbm/qlbm_sample_app.py +1 -1
em/simulation.py
CHANGED
|
@@ -1445,30 +1445,33 @@ def update_value_display(point):
|
|
| 1445 |
|
| 1446 |
def process_uploaded_em_job_result():
|
| 1447 |
"""
|
| 1448 |
-
Process an
|
| 1449 |
|
| 1450 |
This function:
|
| 1451 |
-
1.
|
| 1452 |
-
2.
|
|
|
|
| 1453 |
3. Builds time frames based on user-specified T and dt
|
| 1454 |
4. Generates a Plotly time-series figure
|
| 1455 |
|
| 1456 |
-
|
| 1457 |
-
-
|
| 1458 |
-
-
|
| 1459 |
-
- Simple format: {"field_values": [0.1, 0.2, ...], "times": [0.0, 0.1, ...]}
|
| 1460 |
"""
|
| 1461 |
-
import
|
| 1462 |
-
import json
|
| 1463 |
import plotly.graph_objects as go
|
| 1464 |
|
| 1465 |
if not state.bound:
|
| 1466 |
return
|
| 1467 |
|
| 1468 |
-
# Validate
|
| 1469 |
-
|
| 1470 |
-
if
|
| 1471 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1472 |
return
|
| 1473 |
|
| 1474 |
# Reset messages
|
|
@@ -1482,28 +1485,9 @@ def process_uploaded_em_job_result():
|
|
| 1482 |
def log_to_console(msg):
|
| 1483 |
print(msg)
|
| 1484 |
|
| 1485 |
-
log_to_console("Processing
|
| 1486 |
|
| 1487 |
try:
|
| 1488 |
-
# Handle list or single file
|
| 1489 |
-
file_data = uploaded[0] if isinstance(uploaded, list) else uploaded
|
| 1490 |
-
|
| 1491 |
-
# Get filename for display
|
| 1492 |
-
filename = file_data.get("name", "unknown.json") if isinstance(file_data, dict) else "unknown.json"
|
| 1493 |
-
state.em_job_upload_filename = filename
|
| 1494 |
-
log_to_console(f"Processing file: {filename}")
|
| 1495 |
-
|
| 1496 |
-
# Decode content
|
| 1497 |
-
content = file_data.get("content", "") if isinstance(file_data, dict) else ""
|
| 1498 |
-
|
| 1499 |
-
if isinstance(content, bytes):
|
| 1500 |
-
json_str = content.decode("utf-8")
|
| 1501 |
-
else:
|
| 1502 |
-
if content.startswith("data:"):
|
| 1503 |
-
content = content.split(",", 1)[1]
|
| 1504 |
-
raw_bytes = base64.b64decode(content)
|
| 1505 |
-
json_str = raw_bytes.decode("utf-8")
|
| 1506 |
-
|
| 1507 |
# Parse parameters from UI
|
| 1508 |
field_type = str(state.em_job_field_type or "Ez").strip()
|
| 1509 |
|
|
@@ -1524,77 +1508,125 @@ def process_uploaded_em_job_result():
|
|
| 1524 |
platform = str(state.em_job_platform or "IBM")
|
| 1525 |
|
| 1526 |
log_to_console(f"Parameters: field={field_type}, pos=({monitor_x},{monitor_y}), T={total_time}, dt={snapshot_dt}, nx={nx}, platform={platform}")
|
| 1527 |
-
|
| 1528 |
-
#
|
| 1529 |
-
result = json.loads(json_str)
|
| 1530 |
-
|
| 1531 |
-
# Extract field values based on result structure
|
| 1532 |
field_values = []
|
| 1533 |
times = []
|
| 1534 |
-
|
| 1535 |
-
|
| 1536 |
-
|
| 1537 |
-
|
| 1538 |
-
|
| 1539 |
-
|
| 1540 |
-
|
| 1541 |
-
|
| 1542 |
-
|
| 1543 |
-
|
| 1544 |
-
|
| 1545 |
-
|
| 1546 |
-
|
| 1547 |
-
|
| 1548 |
-
|
| 1549 |
-
|
| 1550 |
-
|
| 1551 |
-
|
| 1552 |
-
|
| 1553 |
-
|
| 1554 |
-
|
| 1555 |
-
|
| 1556 |
-
|
| 1557 |
-
|
| 1558 |
-
|
| 1559 |
-
|
| 1560 |
-
|
| 1561 |
-
|
| 1562 |
-
|
| 1563 |
-
|
| 1564 |
-
|
| 1565 |
-
|
| 1566 |
-
|
| 1567 |
-
|
| 1568 |
-
|
| 1569 |
-
|
| 1570 |
-
|
| 1571 |
-
|
| 1572 |
-
|
| 1573 |
-
|
| 1574 |
-
|
| 1575 |
-
|
| 1576 |
-
|
| 1577 |
-
|
| 1578 |
-
|
| 1579 |
-
|
| 1580 |
-
|
| 1581 |
-
|
| 1582 |
-
|
| 1583 |
-
|
| 1584 |
-
|
| 1585 |
-
|
| 1586 |
-
|
| 1587 |
-
|
| 1588 |
-
|
| 1589 |
-
|
| 1590 |
-
|
| 1591 |
-
|
| 1592 |
-
|
| 1593 |
-
|
| 1594 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1595 |
|
| 1596 |
if not field_values:
|
| 1597 |
-
state.em_job_upload_error = "
|
| 1598 |
state.em_job_is_processing = False
|
| 1599 |
return
|
| 1600 |
|
|
@@ -1688,12 +1720,8 @@ def process_uploaded_em_job_result():
|
|
| 1688 |
state.qpu_plot_position_options = ["All positions", label]
|
| 1689 |
state.qpu_plot_position_filter = "All positions"
|
| 1690 |
|
| 1691 |
-
state.em_job_upload_success = f"✓ Successfully processed {len(field_values)} time step(s) from {
|
| 1692 |
log_to_console(f"Upload processing complete: {len(field_values)} points plotted")
|
| 1693 |
-
|
| 1694 |
-
except json.JSONDecodeError as e:
|
| 1695 |
-
state.em_job_upload_error = f"Invalid JSON file: {e}"
|
| 1696 |
-
log_to_console(f"JSON decode error: {e}")
|
| 1697 |
except Exception as e:
|
| 1698 |
state.em_job_upload_error = f"Error processing job result: {e}"
|
| 1699 |
log_to_console(f"Processing error: {e}")
|
|
|
|
| 1445 |
|
| 1446 |
def process_uploaded_em_job_result():
|
| 1447 |
"""
|
| 1448 |
+
Process an IBM/IonQ EM job by retrieving it directly using the Job ID and generate a time-series plot.
|
| 1449 |
|
| 1450 |
This function:
|
| 1451 |
+
1. Takes the Job ID from user input
|
| 1452 |
+
2. Connects to IBM/IonQ based on platform selection and retrieves the job
|
| 1453 |
+
3. Extracts expectation values (evs) from Estimator results and converts them to field magnitudes
|
| 1454 |
3. Builds time frames based on user-specified T and dt
|
| 1455 |
4. Generates a Plotly time-series figure
|
| 1456 |
|
| 1457 |
+
Note:
|
| 1458 |
+
- This pathway expects the job was submitted by this EM workflow (Estimator-based).
|
| 1459 |
+
- The job is assumed to contain one expectation value per time frame.
|
|
|
|
| 1460 |
"""
|
| 1461 |
+
import os
|
|
|
|
| 1462 |
import plotly.graph_objects as go
|
| 1463 |
|
| 1464 |
if not state.bound:
|
| 1465 |
return
|
| 1466 |
|
| 1467 |
+
# Validate Job ID
|
| 1468 |
+
job_id = None
|
| 1469 |
+
if getattr(state, "em_job_id", None) and str(state.em_job_id).strip():
|
| 1470 |
+
job_id = str(state.em_job_id).strip()
|
| 1471 |
+
if job_id.endswith(".json"):
|
| 1472 |
+
job_id = job_id[:-5]
|
| 1473 |
+
if not job_id:
|
| 1474 |
+
state.em_job_upload_error = "No Job ID provided. Please enter a Job ID."
|
| 1475 |
return
|
| 1476 |
|
| 1477 |
# Reset messages
|
|
|
|
| 1485 |
def log_to_console(msg):
|
| 1486 |
print(msg)
|
| 1487 |
|
| 1488 |
+
log_to_console(f"Processing EM job result for Job ID: {job_id}")
|
| 1489 |
|
| 1490 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1491 |
# Parse parameters from UI
|
| 1492 |
field_type = str(state.em_job_field_type or "Ez").strip()
|
| 1493 |
|
|
|
|
| 1508 |
platform = str(state.em_job_platform or "IBM")
|
| 1509 |
|
| 1510 |
log_to_console(f"Parameters: field={field_type}, pos=({monitor_x},{monitor_y}), T={total_time}, dt={snapshot_dt}, nx={nx}, platform={platform}")
|
| 1511 |
+
|
| 1512 |
+
# Retrieve job results from provider
|
|
|
|
|
|
|
|
|
|
| 1513 |
field_values = []
|
| 1514 |
times = []
|
| 1515 |
+
|
| 1516 |
+
if platform.upper() == "IBM":
|
| 1517 |
+
try:
|
| 1518 |
+
from qiskit_ibm_runtime import QiskitRuntimeService
|
| 1519 |
+
except Exception:
|
| 1520 |
+
state.em_job_upload_error = "qiskit_ibm_runtime package not available. Please install it."
|
| 1521 |
+
state.em_job_is_processing = False
|
| 1522 |
+
return
|
| 1523 |
+
|
| 1524 |
+
try:
|
| 1525 |
+
ibm_token = os.environ.get("API_KEY_IBM_EM")
|
| 1526 |
+
if not ibm_token or not str(ibm_token).strip():
|
| 1527 |
+
state.em_job_upload_error = "IBM API token not found. Set API_KEY_IBM_EM environment variable."
|
| 1528 |
+
state.em_job_is_processing = False
|
| 1529 |
+
return
|
| 1530 |
+
service = QiskitRuntimeService(
|
| 1531 |
+
channel="ibm_cloud",
|
| 1532 |
+
token=ibm_token,
|
| 1533 |
+
instance="crn:v1:bluemix:public:quantum-computing:us-east:a/15157e4350c04a9dab51b8b8a4a93c86:e29afd91-64bf-4a82-8dbf-731e6c213595::",
|
| 1534 |
+
)
|
| 1535 |
+
except Exception as e:
|
| 1536 |
+
state.em_job_upload_error = f"Failed to connect to IBM Quantum: {e}"
|
| 1537 |
+
state.em_job_is_processing = False
|
| 1538 |
+
return
|
| 1539 |
+
|
| 1540 |
+
try:
|
| 1541 |
+
job = service.job(job_id)
|
| 1542 |
+
except Exception as e:
|
| 1543 |
+
state.em_job_upload_error = f"Failed to retrieve IBM job: {e}"
|
| 1544 |
+
state.em_job_is_processing = False
|
| 1545 |
+
return
|
| 1546 |
+
|
| 1547 |
+
try:
|
| 1548 |
+
status = job.status()
|
| 1549 |
+
status_name = status.name if hasattr(status, "name") else str(status)
|
| 1550 |
+
if status_name not in ("DONE", "COMPLETED"):
|
| 1551 |
+
state.em_job_upload_error = f"Job is not complete. Current status: {status_name}"
|
| 1552 |
+
state.em_job_is_processing = False
|
| 1553 |
+
return
|
| 1554 |
+
except Exception:
|
| 1555 |
+
pass
|
| 1556 |
+
|
| 1557 |
+
try:
|
| 1558 |
+
# Support both shapes:
|
| 1559 |
+
# - PrimitiveResult: iterable of pubs -> pub.data.evs
|
| 1560 |
+
# - list-like result where each entry has .data.evs
|
| 1561 |
+
res = job.result()
|
| 1562 |
+
if hasattr(res, "__iter__"):
|
| 1563 |
+
for pub in res:
|
| 1564 |
+
data = getattr(pub, "data", None)
|
| 1565 |
+
evs = getattr(data, "evs", None) if data is not None else None
|
| 1566 |
+
if evs is not None:
|
| 1567 |
+
z_exp = float(np.array(evs).reshape(-1)[0])
|
| 1568 |
+
field_values.append(float(np.sqrt((1 - z_exp) / 2)))
|
| 1569 |
+
elif hasattr(res, "data") and hasattr(res.data, "evs"):
|
| 1570 |
+
z_exp = float(np.array(res.data.evs).reshape(-1)[0])
|
| 1571 |
+
field_values.append(float(np.sqrt((1 - z_exp) / 2)))
|
| 1572 |
+
except Exception as e:
|
| 1573 |
+
state.em_job_upload_error = f"Failed to get job results: {e}"
|
| 1574 |
+
state.em_job_is_processing = False
|
| 1575 |
+
return
|
| 1576 |
+
|
| 1577 |
+
else:
|
| 1578 |
+
# IonQ pathway (Estimator-based in this app)
|
| 1579 |
+
try:
|
| 1580 |
+
from qiskit_ionq import IonQProvider
|
| 1581 |
+
except Exception:
|
| 1582 |
+
state.em_job_upload_error = "qiskit_ionq package not available. Please install it."
|
| 1583 |
+
state.em_job_is_processing = False
|
| 1584 |
+
return
|
| 1585 |
+
|
| 1586 |
+
ionq_token = os.environ.get("API_KEY_IONQ_EM")
|
| 1587 |
+
if not ionq_token or not str(ionq_token).strip():
|
| 1588 |
+
state.em_job_upload_error = "IonQ API token not found. Set API_KEY_IONQ_EM environment variable."
|
| 1589 |
+
state.em_job_is_processing = False
|
| 1590 |
+
return
|
| 1591 |
+
os.environ.setdefault("IONQ_API_TOKEN", ionq_token)
|
| 1592 |
+
|
| 1593 |
+
try:
|
| 1594 |
+
provider = IonQProvider()
|
| 1595 |
+
job = provider.retrieve_job(job_id)
|
| 1596 |
+
except Exception as e:
|
| 1597 |
+
state.em_job_upload_error = f"Failed to retrieve IonQ job: {e}"
|
| 1598 |
+
state.em_job_is_processing = False
|
| 1599 |
+
return
|
| 1600 |
+
|
| 1601 |
+
try:
|
| 1602 |
+
status = job.status()
|
| 1603 |
+
status_name = status.name if hasattr(status, "name") else str(status)
|
| 1604 |
+
if status_name not in ("DONE", "COMPLETED"):
|
| 1605 |
+
state.em_job_upload_error = f"Job is not complete. Current status: {status_name}"
|
| 1606 |
+
state.em_job_is_processing = False
|
| 1607 |
+
return
|
| 1608 |
+
except Exception:
|
| 1609 |
+
pass
|
| 1610 |
+
|
| 1611 |
+
try:
|
| 1612 |
+
res = job.result()
|
| 1613 |
+
if hasattr(res, "__iter__"):
|
| 1614 |
+
for pub in res:
|
| 1615 |
+
data = getattr(pub, "data", None)
|
| 1616 |
+
evs = getattr(data, "evs", None) if data is not None else None
|
| 1617 |
+
if evs is not None:
|
| 1618 |
+
z_exp = float(np.array(evs).reshape(-1)[0])
|
| 1619 |
+
field_values.append(float(np.sqrt((1 - z_exp) / 2)))
|
| 1620 |
+
elif hasattr(res, "data") and hasattr(res.data, "evs"):
|
| 1621 |
+
z_exp = float(np.array(res.data.evs).reshape(-1)[0])
|
| 1622 |
+
field_values.append(float(np.sqrt((1 - z_exp) / 2)))
|
| 1623 |
+
except Exception as e:
|
| 1624 |
+
state.em_job_upload_error = f"Failed to get job results: {e}"
|
| 1625 |
+
state.em_job_is_processing = False
|
| 1626 |
+
return
|
| 1627 |
|
| 1628 |
if not field_values:
|
| 1629 |
+
state.em_job_upload_error = "No field values extracted from job. Ensure the job was submitted by the EM Estimator workflow."
|
| 1630 |
state.em_job_is_processing = False
|
| 1631 |
return
|
| 1632 |
|
|
|
|
| 1720 |
state.qpu_plot_position_options = ["All positions", label]
|
| 1721 |
state.qpu_plot_position_filter = "All positions"
|
| 1722 |
|
| 1723 |
+
state.em_job_upload_success = f"✓ Successfully processed {len(field_values)} time step(s) from {platform} job {job_id}"
|
| 1724 |
log_to_console(f"Upload processing complete: {len(field_values)} points plotted")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1725 |
except Exception as e:
|
| 1726 |
state.em_job_upload_error = f"Error processing job result: {e}"
|
| 1727 |
log_to_console(f"Processing error: {e}")
|
em/state.py
CHANGED
|
@@ -298,12 +298,11 @@ def _init_state_defaults():
|
|
| 298 |
"show_progress": False,
|
| 299 |
"console_logs": "Console initialized...\n",
|
| 300 |
# --- EM Job Upload State ---
|
| 301 |
-
"em_job_upload": None,
|
| 302 |
-
"em_job_upload_filename": "",
|
| 303 |
"em_job_upload_error": "",
|
| 304 |
"em_job_upload_success": "",
|
| 305 |
"em_job_is_processing": False,
|
| 306 |
"em_job_platform": "IBM",
|
|
|
|
| 307 |
"em_job_field_type": "Ez",
|
| 308 |
"em_job_monitor_point": "(0, 0)",
|
| 309 |
"em_job_total_time": 1.0,
|
|
|
|
| 298 |
"show_progress": False,
|
| 299 |
"console_logs": "Console initialized...\n",
|
| 300 |
# --- EM Job Upload State ---
|
|
|
|
|
|
|
| 301 |
"em_job_upload_error": "",
|
| 302 |
"em_job_upload_success": "",
|
| 303 |
"em_job_is_processing": False,
|
| 304 |
"em_job_platform": "IBM",
|
| 305 |
+
"em_job_id": "",
|
| 306 |
"em_job_field_type": "Ez",
|
| 307 |
"em_job_monitor_point": "(0, 0)",
|
| 308 |
"em_job_total_time": 1.0,
|
em/ui.py
CHANGED
|
@@ -494,100 +494,127 @@ def _build_output_preferences_card():
|
|
| 494 |
def _build_job_upload_card():
|
| 495 |
"""Build the Job Result Upload card for loading previously saved QPU results."""
|
| 496 |
with vuetify3.VCard(classes="mb-1", style="font-size: 0.8rem;"):
|
| 497 |
-
with vuetify3.VCardTitle("Upload
|
| 498 |
pass
|
| 499 |
with vuetify3.VCardText(classes="py-1 px-2"):
|
| 500 |
-
trame_html.Div(
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
|
|
|
|
|
|
| 506 |
vuetify3.VSelect(
|
|
|
|
| 507 |
label="Platform",
|
| 508 |
v_model=("em_job_platform", "IBM"),
|
| 509 |
items=("['IBM', 'IonQ']",),
|
| 510 |
density="compact",
|
| 511 |
hide_details=True,
|
| 512 |
color="primary",
|
|
|
|
|
|
|
| 513 |
)
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
density="compact",
|
| 520 |
-
hide_details=True,
|
| 521 |
-
color="primary",
|
| 522 |
-
)
|
| 523 |
-
|
| 524 |
-
# Monitor position row
|
| 525 |
-
with vuetify3.VRow(dense=True, classes="mb-2"):
|
| 526 |
-
with vuetify3.VCol(cols=12):
|
| 527 |
vuetify3.VTextField(
|
| 528 |
-
|
| 529 |
-
|
|
|
|
| 530 |
density="compact",
|
| 531 |
hide_details=True,
|
| 532 |
color="primary",
|
| 533 |
-
|
|
|
|
|
|
|
| 534 |
)
|
| 535 |
-
|
| 536 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
with vuetify3.VRow(dense=True, classes="mb-2"):
|
| 538 |
with vuetify3.VCol(cols=4):
|
| 539 |
-
vuetify3.
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
type="number",
|
| 552 |
-
density="compact",
|
| 553 |
-
hide_details=True,
|
| 554 |
-
color="primary",
|
| 555 |
-
)
|
| 556 |
with vuetify3.VCol(cols=4):
|
| 557 |
-
vuetify3.
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
vuetify3.VFileInput(
|
| 570 |
-
label="Upload Job Result (JSON)",
|
| 571 |
-
v_model=("em_job_upload", None),
|
| 572 |
-
accept=".json",
|
| 573 |
-
prepend_icon="mdi-file-upload",
|
| 574 |
-
density="compact",
|
| 575 |
-
hide_details=True,
|
| 576 |
-
color="primary",
|
| 577 |
-
show_size=True,
|
| 578 |
-
clearable=True,
|
| 579 |
-
)
|
| 580 |
with vuetify3.VCol(cols=4):
|
| 581 |
-
vuetify3.
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 591 |
|
| 592 |
# Success message
|
| 593 |
vuetify3.VAlert(
|
|
|
|
| 494 |
def _build_job_upload_card():
|
| 495 |
"""Build the Job Result Upload card for loading previously saved QPU results."""
|
| 496 |
with vuetify3.VCard(classes="mb-1", style="font-size: 0.8rem;"):
|
| 497 |
+
with vuetify3.VCardTitle("Upload Results", classes="text-subtitle-1 text-primary", style="font-size: 0.9rem; padding: 6px 10px;"):
|
| 498 |
pass
|
| 499 |
with vuetify3.VCardText(classes="py-1 px-2"):
|
| 500 |
+
trame_html.Div(
|
| 501 |
+
"Retrieve completed job results from IBM or IonQ using the Job ID",
|
| 502 |
+
classes="text-caption text-medium-emphasis mb-2",
|
| 503 |
+
)
|
| 504 |
+
|
| 505 |
+
# Platform selector
|
| 506 |
+
with vuetify3.VTooltip(location="top"):
|
| 507 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 508 |
vuetify3.VSelect(
|
| 509 |
+
v_bind="props",
|
| 510 |
label="Platform",
|
| 511 |
v_model=("em_job_platform", "IBM"),
|
| 512 |
items=("['IBM', 'IonQ']",),
|
| 513 |
density="compact",
|
| 514 |
hide_details=True,
|
| 515 |
color="primary",
|
| 516 |
+
classes="mb-2",
|
| 517 |
+
prepend_icon="mdi-chip",
|
| 518 |
)
|
| 519 |
+
trame_html.Span("Select the quantum hardware provider (IBM or IonQ)")
|
| 520 |
+
|
| 521 |
+
# Job ID input
|
| 522 |
+
with vuetify3.VTooltip(location="top"):
|
| 523 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
vuetify3.VTextField(
|
| 525 |
+
v_bind="props",
|
| 526 |
+
label="Job ID",
|
| 527 |
+
v_model=("em_job_id", ""),
|
| 528 |
density="compact",
|
| 529 |
hide_details=True,
|
| 530 |
color="primary",
|
| 531 |
+
classes="mb-2",
|
| 532 |
+
placeholder="e.g., 019b368e-6e22-7525-8512-fd16e0503673",
|
| 533 |
+
prepend_icon="mdi-identifier",
|
| 534 |
)
|
| 535 |
+
trame_html.Span("Enter the Job ID (UUID format from IBM or IonQ)")
|
| 536 |
+
|
| 537 |
+
# Field / monitor / time parameters
|
| 538 |
+
with vuetify3.VRow(dense=True, classes="mb-2"):
|
| 539 |
+
with vuetify3.VCol(cols=6):
|
| 540 |
+
with vuetify3.VTooltip(location="top"):
|
| 541 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 542 |
+
vuetify3.VSelect(
|
| 543 |
+
v_bind="props",
|
| 544 |
+
label="Field Type",
|
| 545 |
+
v_model=("em_job_field_type", "Ez"),
|
| 546 |
+
items=("['Ez', 'Hx', 'Hy']",),
|
| 547 |
+
density="compact",
|
| 548 |
+
hide_details=True,
|
| 549 |
+
color="primary",
|
| 550 |
+
)
|
| 551 |
+
trame_html.Span("Select which field component to plot (Ez, Hx, Hy)")
|
| 552 |
+
with vuetify3.VCol(cols=6):
|
| 553 |
+
with vuetify3.VTooltip(location="top"):
|
| 554 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 555 |
+
vuetify3.VTextField(
|
| 556 |
+
v_bind="props",
|
| 557 |
+
label="Monitor Point (x, y)",
|
| 558 |
+
v_model=("em_job_monitor_point", "(0, 0)"),
|
| 559 |
+
density="compact",
|
| 560 |
+
hide_details=True,
|
| 561 |
+
color="primary",
|
| 562 |
+
placeholder="(x, y)",
|
| 563 |
+
)
|
| 564 |
+
trame_html.Span("Integer grid indices of the monitor point")
|
| 565 |
+
|
| 566 |
with vuetify3.VRow(dense=True, classes="mb-2"):
|
| 567 |
with vuetify3.VCol(cols=4):
|
| 568 |
+
with vuetify3.VTooltip(location="top"):
|
| 569 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 570 |
+
vuetify3.VTextField(
|
| 571 |
+
v_bind="props",
|
| 572 |
+
label="Total Time (T)",
|
| 573 |
+
v_model=("em_job_total_time", 1.0),
|
| 574 |
+
type="number",
|
| 575 |
+
density="compact",
|
| 576 |
+
hide_details=True,
|
| 577 |
+
color="primary",
|
| 578 |
+
)
|
| 579 |
+
trame_html.Span("Total simulation time")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 580 |
with vuetify3.VCol(cols=4):
|
| 581 |
+
with vuetify3.VTooltip(location="top"):
|
| 582 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 583 |
+
vuetify3.VTextField(
|
| 584 |
+
v_bind="props",
|
| 585 |
+
label="Snapshot Δt",
|
| 586 |
+
v_model=("em_job_snapshot_dt", 0.1),
|
| 587 |
+
type="number",
|
| 588 |
+
density="compact",
|
| 589 |
+
hide_details=True,
|
| 590 |
+
color="primary",
|
| 591 |
+
)
|
| 592 |
+
trame_html.Span("Time between snapshots")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
with vuetify3.VCol(cols=4):
|
| 594 |
+
with vuetify3.VTooltip(location="top"):
|
| 595 |
+
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 596 |
+
vuetify3.VTextField(
|
| 597 |
+
v_bind="props",
|
| 598 |
+
label="No. of Points per Direction",
|
| 599 |
+
v_model=("em_job_nx", 4),
|
| 600 |
+
type="number",
|
| 601 |
+
density="compact",
|
| 602 |
+
hide_details=True,
|
| 603 |
+
color="primary",
|
| 604 |
+
)
|
| 605 |
+
trame_html.Span("Grid dimension nx (grid is nx × nx)")
|
| 606 |
+
|
| 607 |
+
vuetify3.VBtn(
|
| 608 |
+
text="Retrieve & Generate Plot",
|
| 609 |
+
color="secondary",
|
| 610 |
+
variant="tonal",
|
| 611 |
+
block=True,
|
| 612 |
+
disabled=("!em_job_id || em_job_is_processing", True),
|
| 613 |
+
loading=("em_job_is_processing", False),
|
| 614 |
+
click=process_uploaded_em_job_result,
|
| 615 |
+
prepend_icon="mdi-chart-box-outline",
|
| 616 |
+
classes="mb-2",
|
| 617 |
+
)
|
| 618 |
|
| 619 |
# Success message
|
| 620 |
vuetify3.VAlert(
|
qlbm/qlbm_sample_app.py
CHANGED
|
@@ -820,7 +820,7 @@ def run_sampling_hw_ionq(
|
|
| 820 |
# IonQ job status polling
|
| 821 |
last_status = None
|
| 822 |
poll_count = 0
|
| 823 |
-
max_polls =
|
| 824 |
|
| 825 |
while poll_count < max_polls:
|
| 826 |
try:
|
|
|
|
| 820 |
# IonQ job status polling
|
| 821 |
last_status = None
|
| 822 |
poll_count = 0
|
| 823 |
+
max_polls = 60000 # ~10 minutes with 1s interval
|
| 824 |
|
| 825 |
while poll_count < max_polls:
|
| 826 |
try:
|