Walkthrough 1: Introduction to Oqtant and Oraqle Quantum Matter Services (QMS)¶
Introduction¶
Welcome to Oqtant
, a python-based object-oriented interface for creating, submitting, and retrieving results from experiments with ultracold quantum matter carried out on Infleqtion's Oraqle platform.
In this introductory tutorial, we will explore the basics of how you, the user, interacts with Oraqle's quantum matter services (QMS) using Oqtant. The general workflow is as follows:
- Create an Oraqle account: https://oraqle.infleqtion.com
- Download and install Oqtant (this!): https://pypi.org/project/oqtant/
- Instantiate an instance of the
OqtantClient
, aka the client, which facilitates communication with QMS (requires authenticating your account). - Create a user-defined
QuantumMatter
, aka matter, object for making and/or manipulating quantum matter. - Submit your matter object to the client. This creates a
OqtantJob
, aka a job, that runs on Oraqle's hardware platform(s) and returns ajob id
(UUID or id) that can be used for checking job status and retrieving results. - When your job is complete, retrieve and analyze results.
For more information, please refer to our documentation: https://gitlab.com/infleqtion/albert/oqtant/-/blob/main/README.md
Also see our companion web application https://oraqle.infleqtion.com/ for quick access to job creation, results, and account management.
Support, feature requests, and bug reports can be submitted here: https://oraqle.infleqtion.com/support
This walkthrough focuses on how to use Oqtant in conjunction with Oraqle QMS. Follow-on walkthroughs will explore user options and Oqtant data structures in significantly more detail.
Note: execution of this entire walkthrough will use quantity 2 of your job quota.
Imports and instantiation of the OqtantClient (requires account authentication)¶
The following block of code will import the needed modules and instantiate a client object that communicates with Oraqle's server(s). Once authenticated, you can safely close that tab and return to this notebook.
NOTE: instantiating the client creates a temporary web server on your machine to handle authenticating with Oraqle QMS. By default, this server will run on port 8080. If that port is unavailable, you can edit default port by passing an port parameter with any value in the range of 8080--8085.
from oqtant.oqtant_client import get_client
from oqtant.schemas.quantum_matter import QuantumMatter
client = get_client(port=8081)
Your first QuantumMatter object and OqtantJob¶
Basic usage of Oqtant involves the creation of a QuantumMatter object, which captures the user-defined inputs that control the behavior of Oraqle hardware. We will explore the available options and underlying data structures in detail in following walkthroughs.
Instantiate a QuantumMatter object¶
For now, we will create a simple object that creates quantum matter at a user-defined target temperature (in nK). We will also give our object a (hopefully meaningful, but optional) name.
matter = QuantumMatter(
temperature=100, name="my first quantum matter" # target temperature (in nK)
)
Submit your QuantumMatter object to the OqtantClient to generate an OqtantJob¶
The next step is to submit our QuantumMatter object to the client using the OqtantClient.submit()
method. This will create an OqtantJob
that will enter the QMS job queue and run on Oraqle hardware when it becomes available. The method itself returns a unique job id (32 character UUID string). Further managment of the job, including retrieving results, will require this id. Here, we will explicitly track the status of our job in the queue by passing the track=True option. The default value is False.
# submission returns the job uuid, e.g. "b26095ac-58bc-4308-a096-13a2544be722"
my_job_id = client.submit(matter, track=True)
Submitting 1 job(s): - Job: my first quantum matter ID: 3d9da73b-db66-46a4-ae26-117230eeee67 Queue Position: 294 Estimated Time: 588 minutes Tracking 1 job(s): - Job: my first quantum matter - RUNNING - COMPLETE All job(s) complete
We can see the job progress through being submitted to the queue (PENDING), being executed on the hardware (RUNNING) and finishing (COMPLETE). The amount of time this sequence takes will depend on the current load on QMS and whether your account is deducting from priority (paid) or free quotas.
Retrieve/fetch the COMPLETE job¶
Once a job is complete, we can proceed to fetching the results. This is accomplished by using the client to get the job (including the results) from the Oraqle server by passing the job id as a parameter to the OqtantClient.get_job()
method. If your job is not yet complete, you can still fetch the job from the server but the output fields will not be populated.
# get job from server, including results if available
# my_job_id = "b26095ac-58bc-4308-a096-13a2544be722"
my_job = client.get_job(my_job_id)
Extracting, visualizing, and analyzing job results¶
Output data fields¶
Once we have a complete job object, we can then extract the result / output using the OqtantJob.output
field. The contents of the output data depends on the initially constructed and submitted matter object. In this example, which uses the default time-of-flight imaging option, the output data contains the following items:
print(my_job.output_fields)
- mot_fluorescence_image - pixels - rows - columns - pixcal - tof_image - pixels - rows - columns - pixcal - tof_fit_image - pixels - rows - columns - pixcal - tof_fit - gaussian_od - gaussian_sigma_x - gaussian_sigma_y - tf_od - tf_x - tf_y - x_0 - y_0 - offset - tof_x_slice - points - tof_y_slice - points - total_mot_atom_number - tof_atom_number - thermal_atom_number - condensed_atom_number - temperature_nk None
In this case, we can see results from a fluorescence image of the magneto-optical trap (mot), a cooling stage early in the sequence that produces the quantum matter that is useful for diagnosing number drifts etc., a time-of-flight (tof) absorption image with pixel data, row/column counts, and a pixel calibration (pixcal, in microns/pixel), a fit version of the tof image based on the calculated thermal/condensed atom populations and the associated temperature. These latter results are derived from fitting a "bimodal" distribution, consisiting of a sum of Gaussian (thermal/classical phase) and Thomas-Fermi (condensed phase) distributions, to the resulting (time of flight) image of the atoms. Data corresponding to the bimodal fit is included in the tof_fit field. All tof image results are given in terms of the optical depth (OD).
Any of the output data contents can be accessed programmatically, e.g.
print("temperature (nK):", my_job.output.temperature_nk)
print("thermal atom population:", my_job.output.thermal_atom_number)
print("condensed atom population:", my_job.output.condensed_atom_number)
temperature (nK): 192 thermal atom population: 8559 condensed atom population: 2611
Extracting output image data¶
Of course, you may want to calculate the quantities above, or any number of others, using the data from the tof (absorption) image of the atoms directly. Raw image data can be accessed programatically, as above, or using the OqtantJob.get_image_data()
helper method. The type of image data to be fetched is passed as an input parameter:
mot_image_data = my_job.get_image_data(image="MOT")
tof_image_data = my_job.get_image_data(image="TIME_OF_FLIGHT")
tof_fit_image_data = my_job.get_image_data(image="TIME_OF_FLIGHT_FIT")
In either approach, image data is returned as a 2D numpy array of values for integer-valued pixel positions. These pixel positions can be converted to position space by accessing the OqtantJob.pix_cal field, which has the units of microns/pixel.
We also have access to pre-calculated cuts of the time-of-flight image along the detected center/peak of the atom ensemble:
x_slice = my_job.get_slice(axis="x")
y_slice = my_job.get_slice(axis="y")
Visualizing results¶
There are a number of tools/methods built into Oqtant for visualizing job outputs.
my_job.plot_tof(figsize=(6, 6))
my_job.plot_slice(axis="x")
Peak OD: 0.970856356851433
These in-built plots show the image of the atoms taken at the end of the experiment, in units of optical depth, as well as cuts along the x and y axes. These latter two plots include solid curves corresponding to the bimodal fit that includes the contributions from the quantum matter's thermal fraction (red curve) and thermal + condensed combination (blue curve).
Of course, the raw data can be used directly for further customization and analysis:
import matplotlib.pyplot as plt
TOF_data = my_job.get_image_data("TIME_OF_FLIGHT")
plt.figure(figsize=(6, 6))
plt.title("Customized plot of the same OD results")
TOF_plot = plt.imshow(TOF_data, origin="lower", cmap="nipy_spectral")
plt.grid(visible=True)
plt.xlabel("x position (pixels)")
plt.ylabel("y position (pixels)")
plt.colorbar(TOF_plot, shrink=0.8)
plt.show()
Job management using the local filesystem¶
While it is completely possible to always retrieve jobs from the Oraqle server, provided they have not been deleted or removed by the user, when dealing with large sets of jobs, or without network connectivity, it is often more convenient and efficient to work with the job data on your local machine.
Saving a job to file¶
To easily reference OqtantJobs from the current or previous sessions it is useful to write their information to a local file. For this, you can use the client.write_job_to_file()
method:
client.write_job_to_file(my_job)
Wrote file: "3d9da73b-db66-46a4-ae26-117230eeee67.txt"
By default, this method will save the job data in a newly created local file with the name *job id*.txt
in the same directory as the current walkthrough / jupyter notebook. Alternatively, you can customize the resulting filename as follows:
client.write_job_to_file(
my_job, file_name=my_job.name # use job name as filename instead
)
Wrote file: "my first quantum matter.txt"
Full control of data saving is made available by providing the full path of the desired output file:
import os
home = os.path.expanduser("~")
client.write_job_to_file(
my_job, file_path=home + "/Documents/" + str(my_job.id) + ".txt"
)
Wrote file: "/home/noah_fitch/Documents/3d9da73b-db66-46a4-ae26-117230eeee67.txt"
Take care not to accidentally write over existing local job data files, especially when specifying custom filenames. Using the default of the job id should help reduce this possibility since that field is unique for each job.
Loading a job from file¶
Retrieving a job from a local file is accomplished by specifying the (local directory) filename or the full file path:
job_from_file = client.load_job_from_file(str(my_job.id) + ".txt")
Wrote file: "3d9da73b-db66-46a4-ae26-117230eeee67.txt"
Automatically saving a job to file¶
Additional details, features, and discussion¶
Including user notes¶
Every QuantumMatter object, and hence also every associated OqtantJob, can hold a note up to 500 characters long. This can be used to add context and additional information. A note remains tied to the job and can be referenced later.
matter_with_note = QuantumMatter(
temperature=100,
name="matter with a note",
note="This is something special that I would like to remember.", # NEW!
)
Mapping of the QuantumMatter object to a JobType
¶
Each QuantumMatter object submitted to the client is mapped to a JobType
that depends on what features and options are specified. This allows Oraqle to enable or disable certain hardware features depending on what the user requires for that particular run of the hardware. We will explore the different job types in future walkthroughs. For our example shown here, our simple QuantumMatter object maps to a BEC job:
print(my_job.job_type)
BEC
The full list of available job types, not all of which are currently supported by the hardware, are as follows:
from bert_schemas import job
for type in job.JobType:
print(type.value)
BEC BARRIER BRAGG TRANSISTOR PAINT_1D
Searching for previous jobs¶
If you need to go back in time to see a history of jobs submitted in previous sessions you can use the OqtantClient.search_jobs()
method. This method provides a way to ask Oraqle for jobs associated to your account that match certain search criteria.
The supported search values are:
- job_type
- name
- submit_start
- submit_end
- notes
Note: submit_start and submit_end must be in ISO format to properly work (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss)
Using these search values Oraqle will return to you any jobs that are associated to your account and match the provided criteria.
client.search_jobs(submit_start="2023-08-20", submit_end="2023-08-31", limit=3)
[{'name': 'my first program', 'origin': 'OQTANT', 'status': 'COMPLETE', 'display': True, 'qpu_name': 'UNDEFINED', 'job_type': 'BEC', 'external_id': 'db9a80aa-dc88-494a-93b2-e5d4378bb2f0', 'time_submit': '2023-08-25T16:50:15.537140'}, {'name': 'batch job name', 'origin': 'OQTANT', 'status': 'COMPLETE', 'display': True, 'qpu_name': 'UNDEFINED', 'job_type': 'BEC', 'external_id': 'a1076a4f-1830-47b9-aa04-7f4ee9ea8660', 'time_submit': '2023-08-22T20:14:50.453972'}, {'name': 'program 4 of 4', 'origin': 'OQTANT', 'status': 'COMPLETE', 'display': True, 'qpu_name': 'UNDEFINED', 'job_type': 'BEC', 'external_id': 'b49a2d22-8a9c-4a97-8f08-8b5fcf51b3e8', 'time_submit': '2023-08-22T20:14:08.564534'}]
Showing the current status of your jobs in the queue¶
When executing many jobs on Oraqle QMS, it is useful to be able to check the status of your submitted jobs without fetching each job individually and checking the status field. This can be accomplished using the OqtantClient.show_queue_status() method, which accepts the same filters as the OqtantClient.search_jobs() method explored above.
client.show_queue_status(submit_start="20230801")
Job ID Job Status Time submitted Job Name -------- ------------ ---------------- ----------
If you would like to also see completed jobs, you can pass the include_complete=True option:
# show queue status for the month of August 2023, including COMPLETE jobs:
client.show_queue_status(
submit_start="20230801",
submit_end="20230831",
include_complete=True,
limit=20, # limit the number of results shown
)
Job ID Job Status Time submitted Job Name ------------------------------------ ------------ -------------------------- ------------------------------------ db9a80aa-dc88-494a-93b2-e5d4378bb2f0 COMPLETE 2023-08-25T16:50:15.537140 my first program a1076a4f-1830-47b9-aa04-7f4ee9ea8660 COMPLETE 2023-08-22T20:14:50.453972 batch job name b49a2d22-8a9c-4a97-8f08-8b5fcf51b3e8 COMPLETE 2023-08-22T20:14:08.564534 program 4 of 4 dabec593-aba8-44e9-95fa-7855ac304738 COMPLETE 2023-08-22T20:14:08.161604 program 3 of 4 7337d59f-6c7a-4761-a1f4-a70a8496e22d COMPLETE 2023-08-22T20:14:07.772585 program 2 of 4 72b4927f-9d3f-4ec2-a9da-2e4ae560f72c COMPLETE 2023-08-22T20:14:07.353668 program 1 of 4 97bd5e7e-bfcb-4baf-ae95-89746d26f3c9 COMPLETE 2023-08-22T20:11:20.525009 my first program 4e9ae649-a449-4157-913d-6f5267049dc2 COMPLETE 2023-08-21T14:43:09.094472 batch job name ba574f28-6300-4210-943f-9bcd24f9efe1 COMPLETE 2023-08-21T14:23:49.598577 program 4 of 4 6e7cbae1-2d2a-43cc-9587-a480b4b3d879 COMPLETE 2023-08-21T14:23:49.241456 program 3 of 4 1ad0fe57-3ae0-4041-b5d5-70e6633c8c17 COMPLETE 2023-08-21T14:23:48.800969 program 2 of 4 fe728e7b-bba5-4a1f-ae76-69cd8aca096c COMPLETE 2023-08-21T14:23:48.292503 program 1 of 4 01736b50-6d5d-4139-be0b-4e3a59280e95 COMPLETE 2023-08-21T04:06:21.503342 QM program w/ lifetime + tof control e95a4af4-5d46-4890-968e-6c04483bbf65 COMPLETE 2023-08-21T03:16:59.176233 my first program 1b6d48f9-c586-452a-b0a3-5607441e8230 COMPLETE 2023-08-20T15:02:40.282007 my first program 4b40ac59-285e-474e-9925-a43084644378 COMPLETE 2023-08-20T14:51:38.662446 my first program cc330f4c-9483-4797-a3b5-c8db469756f4 COMPLETE 2023-08-20T03:10:21.474037 batch job name ca1fb06f-c797-40b6-88ed-e25b6f800117 COMPLETE 2023-08-20T03:01:23.539382 batch job name 9ddc4f37-8bca-490e-86ab-c4610d0e2c95 COMPLETE 2023-08-20T02:48:21.507451 my first program 4080c76a-940a-4293-81f1-6413170b97bc COMPLETE 2023-08-20T02:46:17.563003 program 4 of 4 9bff2751-3e19-45c2-b091-6938013316ad COMPLETE 2023-08-20T02:46:16.947324 program 3 of 4 96d538bb-d05b-487f-b93f-63429c2b7a34 COMPLETE 2023-08-20T02:46:16.376419 program 2 of 4 5a005462-461e-42e1-ac02-68f44754c1ae COMPLETE 2023-08-20T02:46:15.948562 program 1 of 4 35fcb1c0-5f25-4c58-b3ed-a89893ef7e3f COMPLETE 2023-08-20T02:45:52.362947 my first program 1456106d-f734-4630-bcb1-c9e3af291065 COMPLETE 2023-08-20T02:35:07.489782 program 4 of 4 6f76b0cf-1bb0-4f0e-a4a6-f191ec556c44 COMPLETE 2023-08-20T02:35:06.613275 program 3 of 4 66372d01-9bac-4903-a49a-a652e2cda756 COMPLETE 2023-08-20T02:35:06.237922 program 2 of 4 44e3050d-c15d-4288-a1a6-aa04ba483db2 COMPLETE 2023-08-20T02:35:05.846521 program 1 of 4 38cdf96a-6b01-49fd-a601-561790f04b69 COMPLETE 2023-08-19T04:20:58.257284 program 4 of 4 36d7e970-0be3-4de0-83dd-1a4e469ed7a4 COMPLETE 2023-08-19T04:20:57.722123 program 3 of 4 7cf65430-06a6-4671-8df5-9b1d5f6ca410 COMPLETE 2023-08-19T04:20:57.311595 program 2 of 4 0298891d-ab2f-41c4-ba77-df0eff07c26e COMPLETE 2023-08-19T04:20:56.880924 program 1 of 4 bd8d9d03-fb3e-4928-8974-a65599d90947 COMPLETE 2023-08-19T04:20:24.520163 program 4 of 4 b56ff043-7a3d-47fd-9732-8cc4cddedd29 COMPLETE 2023-08-19T04:20:24.090569 program 3 of 4 5e6e2496-c2d0-40de-b205-7498eefed4de COMPLETE 2023-08-19T04:20:23.707276 program 2 of 4 05a3bbbc-00e4-4f9e-baaa-039fb35f3f46 COMPLETE 2023-08-19T04:20:23.307357 program 1 of 4 ad18ea34-27cc-49ae-8992-57d080f2229b COMPLETE 2023-08-19T04:12:28.797705 quantum matter program 5cc4f782-d02b-4899-a3f7-59c2ebead0c2 COMPLETE 2023-08-19T04:12:28.278917 quantum matter program 869cb923-f450-4559-b369-91ae1858ec1b COMPLETE 2023-08-19T04:12:27.872695 quantum matter program a5991571-2bd6-430b-9941-c44c1db8b350 COMPLETE 2023-08-19T04:12:27.268903 quantum matter program e2b6a8b1-d097-4603-afa7-46f0e722a2c5 COMPLETE 2023-08-19T04:12:26.867518 quantum matter program d6744607-3a7a-4cd2-8ede-4a1071668ad5 COMPLETE 2023-08-19T04:10:35.228202 my first program a9b7a465-9daa-46c3-a10d-66b404cc50b8 COMPLETE 2023-08-19T04:08:47.060686 quantum matter program a354fe67-1001-424e-80ad-1405228552b7 COMPLETE 2023-08-19T04:08:46.646112 quantum matter program 5f8a0607-c8e2-405c-995c-3bc2ebc1df63 COMPLETE 2023-08-19T04:08:46.190501 quantum matter program 36072126-7e18-4b61-8e4c-8de8ad04c2f7 COMPLETE 2023-08-19T04:08:45.548713 quantum matter program a64badee-5f2c-4ee6-9e32-cbbf89657ca6 COMPLETE 2023-08-19T04:08:45.194942 quantum matter program 6b35debe-6e05-478f-8fa7-e49840eb67da COMPLETE 2023-08-19T04:08:20.433448 my first program e44ea84d-d35e-4d9f-af86-44e640e098a6 COMPLETE 2023-08-19T03:57:42.408209 program5 79e06d3f-b66f-4508-84cd-7a70e55e6845 COMPLETE 2023-08-19T03:57:42.023139 program4
Querying your current job quota¶
Currently, each user of Oraqle QMS has limits on the number of jobs they can submit per day, etc. Detailed management of your allocated job quota can be accomplished using the web app. From Oqtant, you can show your current limits as follows:
client.show_job_limits()
daily_limit 1000 daily_used 0 daily_remaining 1000 purchased None purchased_remaining None
Units¶
Oqtant uses units that are natural choices for dealing with the quantum matter produced and manipulated by the Oraqle platform. The table below is a summary of relevant units used throughout this and following walkthroughs. Some of these objects/quantities have not yet been encountered, but will be shortly.
Quantity | Units | Notes |
---|---|---|
time | milliseconds (ms, $10^{-3}$ m) | |
frequency | megahertz (MHz, $10^6$ Hz) | Relative to the energetic trap bottom, $\geq 0$ |
powers | milliwatts (mW, $10^{-3}$ W) | Power radiated by an RF loop antenna adjacent to the cold atom sample, $\geq 0$ |
temperature | nanokelvin (nK, $10^{-9}$ K) | |
barrier height | kilohertz (kHz, $10^{3}$ Hz) | Energetic height / Planck's constant |
barrier position | microns ($\mu m$, $10^{-6}$ m) | Center of barrier |
barrier width | microns ($\mu m$, $10^{-6}$ m) | Shape-dependent width parameter |
landscape potential | kilohertz (kHz, $10^{3}$ Hz) | Energetic height / Planck's constant |