Skip to content

Creating a schema

To create a knowledge base (KB) schema, start by creating an empty file called schema.py located alongside your Jupyter notebooks.

Using the qruise CLI tool?

If you used the qruise flow init command to initialise your directory structure, the schema.py file will already be there.

The core schema

The schema file defines the data model for the information stored in the knowledge base. It is extremely flexible and user-configurable, but it must also contain some basic elements to ensure it conforms to the rest of QruiseOS. The easiest way to achieve that is to simply extend the QruiseOS core schema, as shown in the following code snippet:

schema.py
from qruise.experiment.schema.core import CoreSchema
from qruise.kb import Schema


with Schema(
    title="My schema",
    extends=CoreSchema,
) as MySchema:
    pass

This guarantees that all the necessary building blocks are present in the knowledge base, but in order to be useful, we still need to add more elements to it.

Extending the core schema: adding new hardware components

One of the purposes of the knowledge base is to store calibration data. Because quantum computing setups differ between each other, the core schema does not come with models of all possible elements already provided. However, it provides building blocks that can be used to define hardware components.

Consider, for instance, that besides the core schema elements, you also want to store information about flux crosstalk. You can achieve that by extending the schema in the following way:

schema.py
from qruise.experiment.schema.core import Component, CoreSchema, Entity, Quantity
from qruise.kb import Schema

with Schema(
    title="My schema",
    extends=CoreSchema,
) as MySchema:
    class FluxCrosstalk(Entity):
        name: str
        _key = LexicalKey("name")
        target: Component
        """
        Target qubit or coupler that is affected by the flux pulse.
        """
        biased: Component
        """
        Qubit or coupler that is biased by the flux pulse.
        """
        crosstalk: Quantity
        """
        Crosstalk coefficient, in fraction of the flux pulse amplitude.
        It defines the pulse amplitude to compensate the crosstalk.
        It is a dimensionless value, typically in the range of -1 to 1.
        """

Note the highlighted section, showing the FluxCrosstalk class. This class represents the knowledge about the flux crosstalk phenomenon that will be stored in the knowledge base.

Schema elements are Python classes, hence they can also declare methods. This comes in handy for tasks such as finding related entities. For instance, we can extend the base Qubit class to return the connected drive:

schema.py
from qruise.experiment.schema.core import Component, CoreSchema, Entity, Quantity, Qubit
from qruise.kb import Schema

with Schema(
    title="My schema",
    extends=CoreSchema,
) as MySchema:
    class FluxCrosstalk(Entity):
        name: str
        _key = LexicalKey("name")
        target: Component
        """
        Target qubit or coupler that is affected by the flux pulse.
        """
        biased: Component
        """
        Qubit or coupler that is biased by the flux pulse.
        """
        crosstalk: Quantity
        """
        Crosstalk coefficient, in fraction of the flux pulse amplitude.
        It defines the pulse amplitude to compensate the crosstalk.
        It is a dimensionless value, typically in the range of -1 to 1.
        """

    class Qubit(Qubit):
        def get_drive(self):
            return next(
                iter(
                    drive
                    for drive in self._schema.types["Drive"].get_instances()
                    if drive.connected[0] == self
                )
            )

Extending the core schema: adding experiments

With the hardware components defined, you will want to add experiment data to the knowledge base. You can either write your own schema classes, or use one of the 40+ predefined experiments that QruiseOS comes packaged with.

For instance, to add the pulsed qubit spectroscopy, resonator spectroscopy, and T1 experiments, add the following lines to your schema.py file:

schema.py
from qruise.experiment.schema.core import Component, CoreSchema, Entity, Quantity, Qubit
from qruise.experiment.schema.experiments import QubitSpectroscopy, ResonatorSpectroscopy, T1
from qruise.kb import Schema

with Schema(
    title="My schema",
    extends=CoreSchema,
) as MySchema:
    class FluxCrosstalk(Entity):
        name: str
        _key = LexicalKey("name")
        target: Component
        """
        Target qubit or coupler that is affected by the flux pulse.
        """
        biased: Component
        """
        Qubit or coupler that is biased by the flux pulse.
        """
        crosstalk: Quantity
        """
        Crosstalk coefficient, in fraction of the flux pulse amplitude.
        It defines the pulse amplitude to compensate the crosstalk.
        It is a dimensionless value, typically in the range of -1 to 1.
        """

    class Qubit(Qubit):
        def get_drive(self):
            return next(
                iter(
                    drive
                    for drive in self._schema.types["Drive"].get_instances()
                    if drive.connected[0] == self
                )
            )

    class QubitSpectroscopy(QubitSpectroscopy):
        pass

    class ResonatorSpectroscopy(ResonatorSpectroscopy):
        pass

    class T1(T1):
        pass

Notice that the definitions of the classes are empty &ndash they only contain a single pass statement. You can, of course, put anything you might feel is necessary for your particular setup. As an example, you could add a comment field to the T1 experiment class in the following way:

class T1(T1):
    comment: str

You can also add a completely new experiment class by extending the qruise.experiment.schema.core.Experiment class. For instance, consider an experiment called MyExperiment where you measure three parameters, called a, b, and c. This can be easily incorporated into the schema:

schema.py
from qruise.experiment.schema.core import Component, CoreSchema, Entity, Experiment, Quantity, Qubit
from qruise.experiment.schema.experiments import QubitSpectroscopy, ResonatorSpectroscopy, T1
from qruise.kb import Schema

with Schema(
    title="My schema",
    extends=CoreSchema,
) as MySchema:
    class FluxCrosstalk(Entity):
        name: str
        _key = LexicalKey("name")
        target: Component
        """
        Target qubit or coupler that is affected by the flux pulse.
        """
        biased: Component
        """
        Qubit or coupler that is biased by the flux pulse.
        """
        crosstalk: Quantity
        """
        Crosstalk coefficient, in fraction of the flux pulse amplitude.
        It defines the pulse amplitude to compensate the crosstalk.
        It is a dimensionless value, typically in the range of -1 to 1.
        """

    class Qubit(Qubit):
        def get_drive(self):
            return next(
                iter(
                    drive
                    for drive in self._schema.types["Drive"].get_instances()
                    if drive.connected[0] == self
                )
            )

    class QubitSpectroscopy(QubitSpectroscopy):
        pass

    class ResonatorSpectroscopy(ResonatorSpectroscopy):
        pass

    class T1(T1):
        pass

    class MyExperiment(Experiment):
        a: Quantity
        b: Quantity
        c: Quantity