{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "691824b4",
   "metadata": {},
   "source": [
    "# Setting up Boulder Opal with Qblox controllers\n",
    "\n",
    "**Connect a Qblox cluster to Boulder Opal**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6918body",
   "metadata": {},
   "source": [
    "Qblox instruments provide modular control through dedicated RF and baseband modules for qubit drive, readout, and flux. The `boulderopalscaleup` package connects to a Qblox system through a `Runtime` object that manages the controller connection and routes experiment execution to the correct backend.\n",
    "\n",
    "In this tutorial, you will configure a connection to a Qblox cluster, register it with the Boulder Opal runtime, instantiate the client, and create a virtual device from a YAML configuration.\n",
    "\n",
    "You will need a Q-CTRL account with an API key and organization slug, a Qblox cluster reachable from your network with the `qblox-instruments` package installed, and a device configuration YAML provided by Q-CTRL.\n",
    "\n",
    "**Note:** You will need to install `qblox-instruments`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2aabb4ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install qblox-instruments==1.1.1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sec01-md",
   "metadata": {},
   "source": [
    "## 1. Connect to the Qblox cluster\n",
    "\n",
    "For a Qblox system, you describe each cluster with a `QbloxClusterInfo` object that carries the cluster name and host IP address. Replace the placeholder strings with the ones that apply to your device.\n",
    "\n",
    "Once the system is described, you create the runtime with `Runtime.new()` and register the hardware with `runtime.add_system(QbloxSystemInfo(...))`.\n",
    "\n",
    "**Note:** It is important to configure the `QbloxClusterInfo` and `QbloxSystemInfo` properly to reflect your controller's setup. Read the reference documentation for a complete explanation of all their parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "664fc506",
   "metadata": {},
   "outputs": [],
   "source": [
    "from boulderopalscaleup.runtime import Runtime\n",
    "from boulderopalscaleup.runtime.systems.qblox import QbloxClusterInfo, QbloxSystemInfo\n",
    "\n",
    "qblox_clusters = [QbloxClusterInfo(name=\"<cluster name>\", host=\"<cluster IP address>\")]\n",
    "\n",
    "runtime = Runtime.new()\n",
    "runtime.add_system(QbloxSystemInfo(clusters=qblox_clusters))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sec02-md",
   "metadata": {},
   "source": [
    "## 2. Initialize the client\n",
    "\n",
    "Create the client and pass it the runtime you just configured along with your Q-CTRL API key and organization slug. Replace the placeholder strings with the credentials issued by Q-CTRL."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b034d7da",
   "metadata": {},
   "outputs": [],
   "source": [
    "from boulderopalscaleup import QctrlScaleUpClient\n",
    "\n",
    "client = QctrlScaleUpClient(\n",
    "    runtime=runtime,\n",
    "    api_key=\"<your API key>\",\n",
    "    organization_slug=\"<your organization slug>\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sec03-md",
   "metadata": {},
   "source": [
    "## 3. Create and select the virtual device\n",
    "\n",
    "Before running any programs on your physical device, you must create a virtual device in the Q-CTRL environment. The `create_device()` call uploads a YAML configuration file that describes the layout of your QPU and the wiring of the control hardware that drives it, and registers the new virtual device under your organization. During this step, make sure you use the correct configuration files that are specifically for Qblox controllers. This ensures the setup complies with the respective Qblox syntax and support modules.\n",
    "\n",
    "**Note:** Q-CTRL provides a template YAML for each supported QPU model and supported controller. Replace `./device_config.yaml` with the name of the file provided to you."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cdb8c974",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "# The YAML file defines the wiring and other configurations for your device\n",
    "device_yaml_path = Path(\"./device_config.yaml\")\n",
    "\n",
    "# Give the virtual device a unique name\n",
    "device_name = \"device_name\"\n",
    "\n",
    "# Add this named virtual device to the Q-CTRL environment, if not already present\n",
    "if device_name not in [device.name for device in await client.get_devices()]:\n",
    "    await client.create_device(device_name, device_config=device_yaml_path)\n",
    "\n",
    "# Mark that device as the current device to use in subsequent routines and experiments\n",
    "await client.set_current_device(device_name)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
