Skip to main content

API for pulling data from Maybell Quantum dilution refrigerators.

Project description

Maybell Quantum API

Public Python API to Maybell Quantum dilution refrigerators.

Getting Started

pip install maybell_quantum

https://pypi.org/project/maybell-quantum/

Dependencies

Below are the direct dependencies of this API:

  • influxdb-client
  • matplotlib (optional)

Latest Additions

  • pymongo support - MongoTimeSeries
  • Pandas support - MongoTimeSeries.fetch_pandas returns a pandas.DataFrame

Coming Soon

  • Live plotting.
  • User-defined data injection.

Quick Start for the Impatient

Cloud Access:

First off you'll need two things from Maybell Quantum:

  1. An API Token (e.g. 'EDECC12...THISouWIS_0oZ_A_P-yFAKE8...ITOKENO...A==')
  2. InfluxDB bucket associated with the API Token. (e.g. "Acme Quantum Computers")

Local Access:

Jump to the Local Access Guide and then come back here.

Copy and paste the following snippet and save it to a file called plot_temperature_data.py:

NB: The default values for url and org should work fine for all customers.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import logging
import os

import matplotlib.pyplot

from maybell_quantum.fridgedb import FridgeDB
from maybell_quantum.fridgedb import TimeRange

from maybell_quantum.helpers import plot
from maybell_quantum.helpers import pretty_print_result

if "INFLUXDB_TOKEN" not in os.environ:
    logging.fatal(
        "INFLUXDB_TOKEN environment variable is not set.  Can't connect without it."
    )
    exit(1)
token = os.environ["INFLUXDB_TOKEN"]
# TODO: edit the following line with your bucket name
bucket = "<maybell-assigned-bucket-name>"
url = "https://us-east-1-1.aws.cloud2.influxdata.com"
org = "Maybell Quantum"

fdb = FridgeDB(org=org, url=url, token=token, bucket=bucket)

stop_time = datetime.now(timezone.utc)
start_time = stop_time - timedelta(hours=10)
time_range = TimeRange(start_time, stop_time)

matplotlib.pyplot.figure()
thermometers = ["mxp"]
temperatures = fdb.fetch(time_range, thermometers)
plot(thermometers, "temperature", temperatures, saveas="temperatures.png")
pretty_print_result(temperatures)
export INFLUXDB_TOKEN=<your-company-token>
python3 plot_temperature_data.py

Using Local Timezone

We recommend users manage queries using Coordinated Universal Time (UTC). The frigdedb TimeRange dataclass must be in UTC. Daylight savings rollovers or rollbacks can result in queries for more or less data than you may expect. However, for small sessions where it may be convenient, you can provide time ranges in local time using Timezone-Aware datetime. Use zoneinfo.available_timezones() to see a list of supported regions.

from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

tz = ZoneInfo("America/Los_Angeles")

# create a Timezone-Aware `datetime` object using the tzinfo parameter
start_time_local = datetime(year=2024, month=12, day=4, hour=6, tzinfo=tz)
start_time_utc = start_time_local.astimezone(ZoneInfo("UTC"))  # UTC conversion
stop_time_utc = start_time_local + timedelta(8)

time_range = TimeRange(start_time_utc, stop_time_utc)

In More Detail (Optional)

from fridgedb import FridgeDB
org = 'Maybell Quantum'
url = 'https://us-east-1-1.aws.cloud2.influxdata.com'
token = 'EDECC12GXgRO8grdiLPD7tXUVY7QL36THISouWIIS_0oZ_4SAfP-yFAKE8I3ZFBg0TOKENOko1fZikpEmq43gA=='
bucket = 'Acme Quantum Computing'
fdb = FridgeDB(org=org, url=url, token=token, bucket=bucket)

Get Temperature Data

You'll need to know the names of the thermometers for your specific system. Typical values are currently hard-coded as static class variables in FridgeDB.

from fridgedb import FridgeDB, TimeRange
from helpers import pretty_print_result, plot 
from datetime import datetime, timedelta, timezone
print(f"{FridgeDB.sensor_names}")
print(f"{FridgeDB.device_names}")
org = 'Maybell Quantum'
url = 'https://us-east-1-1.aws.cloud2.influxdata.com'
token = '<your_api_token>'
bucket = '<your_maybell_assigned_bucket>'
fdb = FridgeDB(org=org, url=url, token=token, bucket=bucket)
time_range = TimeRange(start_time=datetime.now(timezone.utc) - timedelta(minutes=45), stop_time=datetime.now(timezone.utc))
thermometers = ["mxp", "prp", "rgp", "stp"]
temperatures = fdb.fetch(time_range, thermometers)
plot(thermometers, 'temperature', temperatures, saveas="temperatures.png")
pretty_print_result(temperatures)
Step by Step Explanation

Start with importing the necessary classes and some helper functions, like pretty_print_result and plot. Next set the variable needed to create, and pull data from, an InfluxDB client. NB: you'll need to get a unique API token from Maybell, as well as the name of the bucket(s) for your fridge(s).

In [1]: from fridgedb import FridgeDB, TimeRange
   ...: from helpers import pretty_print_result, plot
   ...: from datetime import datetime, timedelta
In [2]: org = 'Maybell Quantum'
   ...: url = 'https://us-east-1-1.aws.cloud2.influxdata.com'
   ...: token = '<your_api_token>'
   ...: bucket = '<your_maybell_assigned_bucket>'

Now that we have an instance of FridgeDB we can fetch data. The TimeRange dataclass has just two members: start_time and stop_time (both Python datetime objects). Below is an example of how to fetch data for the last 45 minutes.

In [3]: fdb = FridgeDB(org=org, url=url, token=token, bucket=bucket)
   ...: time_range = TimeRange(start_time=datetime.utcnow() - timedelta(minutes=45), stop_time=datetime.utcnow())
   ...: temperatures = fdb.fetch(time_range, ["mxp", "prp", "rgp", "stp"])
   ...: print(f"{fdb.sensor_names}")
   ...: print(f"{fdb.device_names}")
['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'cfp', 'f1', 'icp', 'mxp', 'prp', 'rgp', 'stp']
['v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8', 'v9', 'v10', 'v11', 'v12', 'v13', 'v14', 'v15', 'v16', 'v17', 'v18', 'v19', 'v20', 'v21', 'v22', 'v23', 'v24', 'v25', 'v26', 'pm1', 'pm2', 'pm3', 'pm4', 'pm5', 'warmup', 'still', 'sample', 'cp1', 'cp2', 'inv1']

The result that's returned is a dictionary of dictionaries, where the first key is the name of the device or sensor, and the second key is the field of interest (e.g. "temperature"). Below shows the structure in more detail for clarity.

In [4]: pretty_print_result(temperatures)
{ 'mxp' : 
    {
        'power' = [46.73, 49.89,..., 2.12, 57.52]
        'quadrature' = [37.34, 68.39,..., 10.02, 40.96]
        'resistance' = [62.17, 19.55,..., 25.76, 26.95]
        'temperature' = [77.86, 4.62,..., 58.08, 39.46]
    }
}
{ 'prp' : 
    {
        'power' = [57.88, 35.83,..., 84.21, 20.50]
        'quadrature' = [2.24, 52.69,..., 66.20, 94.42]
        'resistance' = [92.64, 11.34,..., 59.66, 80.26]
        'temperature' = [74.98, 6.59,..., 4.66, 24.80]
    }
}
{ 'rgp' : 
    {
        'power' = [93.86, 96.91,..., 53.15, 49.18]
        'quadrature' = [61.12, 98.45,..., 66.95, 98.52]
        'resistance' = [58.18, 30.39,..., 66.84, 41.51]
        'temperature' = [5.97, 15.57,..., 37.27, 38.87]
    }
}
{ 'stp' : 
    {
        'power' = [1.99, 65.45,..., 49.96, 85.84]
        'quadrature' = [58.32, 6.96,..., 18.05, 69.87]
        'resistance' = [55.72, 30.75,..., 68.62, 15.45]
        'temperature' = [17.65, 39.26,..., 58.94, 28.07]
    }
}

Get All Sensor Data

For convenience, a thin wrapper around fetch is provided that gets all the sensor and device data for a given time range.

machine_state = fdb.fetch_all(time_range)
Get All Sensor Data Since a Given Time

For convenience, another thin wrapper around fetch is provided that gets all the sensor and device data from now until <timedelta>.

The following snippets pulls the entire machine state (all devices and sensors) for the last hour.

since = datetime.timedelta(hours=1)
machine_state = fdb.last(since)

Details - Sensor and Device Data Model

Snapshots of the fridge state are stored in an InfluxDB database at set intervals (default is every 10s).

Each system consists of sensors and devices. Sensors are read-only (e.g. pressure gauges and thermometers) and devices can be issued commands (e.g. valves can be opened and closed).

Sensors

All sensors below have their _tag set to "sensor" (see InfluxDB Tags).

Thermometer

{
    "_type" : "thermometer", 
    "_tag": "sensor",
    "temperature": float,
    "resistance": float,
    "quadrature": float,
    "power": float,
}

Pressure

{
    "_type" : "pressure", 
    "_tag": "sensor",
    "pressure": float,
}

BGA - Binary Gas Analyzer

{ 
    "_type" : "bga", 
    "_tag": "sensor",
    "percent": float
}

Flow

{
    "_type" : "flow", 
    "_tag": "sensor",
    "pressure": float,
    "temperature": float,
    "volumetric_flow": float,
    "mass_flow": float,
}

Devices

All devices below have their _tag set to "device" (see InfluxDB Tags).

Valve

{
    "_type" : "valve", 
    "_tag": "device",
    "open": bool,
}

Trap

{
    "_type" : "trap", 
    "_tag": "device",
    "output": float,
}

Pump

{
    "_type" : "pump", 
    "_tag": "device",
    "active": bool,
}

Heater

{
    "_type" : "", 
    "_tag": "device",
    "power": float,
    "current": float,
    "voltage": float,
    "native": float,
}

Loop

{
    "_type" : "loop", 
    "_tag": "device",
    "setpoint": float,
    "gain": float,
    "integral": float,
    "derivative": float,
    "ramp_rate": float,
    "state": bool,
}

Turbo

{
    "_type" : "turbo", 
    "_tag": "device",
    "state": bool,
    "speed": int,
    "converter": int,
    "motor": int,
    "bearing": int,
    "setpoint": int,
    "voltage": int,
    "error": bool,
}

Ecodry

{
    "_type" : "ecodry", 
    "_tag": "device",
    "setpoint": float,
    "frequency": float,
    "current": float,
    "voltage": float,
    "bus_voltage": float,
    "power": float,
    "state": bool,
}

Inverter

{
    "_type" : "inverter", 
    "_tag": "device",
    "state": bool,
    "frequency": float,
    "current": float,
    "voltage": float,
    "alarm": Alarm,
}
class Alarm(enum.Enum):
    """Enumerate the toshiba alarm flags."""

    NO_ALARM = 0
    ALARM_OVER_CURRENT = 1 << 0
    ALARM_INVERTER_OVERLOAD = 1 << 1
    ALARM_MOTOR_OVERLOAD = 1 << 2
    ALARM_OVERHEAT = 1 << 3
    ALARM_OVER_VOLTAGE = 1 << 4
    ALARM_UNDER_VOLTAGE = 1 << 5
    ALARM_MAIN_OVERLOAD = 1 << 6
    ALARM_LOW_CURRENT = 1 << 7
    ALARM_OVER_TORQUE = 1 << 8
    ALARM_BRAKE_OVERLOAD = 1 << 9
    ALARM_OPERATION_HOURS = 1 << 10
    ALARM_OPTION_COMMUNICATION = 1 << 11
    ALARM_SERIAL_COMMUNICATION = 1 << 12
    ALARM_MAIN_VOLTAGE = 1 << 13

Compressor

{
    "_type" : "compressor", 
    "_tag": "device",
    "state": bool,
    "discharge_temperature": float,
    "outlet_tempertaure": float,
    "inlet_temperature": float,
    "return_pressure": float,
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maybell_quantum-1.1.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

maybell_quantum-1.1.0-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file maybell_quantum-1.1.0.tar.gz.

File metadata

  • Download URL: maybell_quantum-1.1.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for maybell_quantum-1.1.0.tar.gz
Algorithm Hash digest
SHA256 3abc91fb5cfda8975c941cb5cf82b6ccd6a26dd98fac525917c9f04efc8dd28a
MD5 6f1bf817e6a6b7fabc15a99b192b635b
BLAKE2b-256 846061efd4d9735cf84466785518cda6f6a047d2e98b6ae80af180d65a6b2fd9

See more details on using hashes here.

File details

Details for the file maybell_quantum-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for maybell_quantum-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 28706f63e855c491374e2de16bc780e8c52af4f5d2d72e0a77d8689f1cee1819
MD5 96f29ca850709f1a94111140367fef8e
BLAKE2b-256 765b65e8ed7f40eefa86403a1cb4885ece9316417858018062fe23b38b33d75b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page