qibocal.auto package#

Autocalibration runner.

Submodules#

qibocal.auto.draw module#

Drawing utilities for execution graphs.

qibocal.auto.draw.draw(graph: Graph, ax=None)[source]#

Draw a graph according to its priority.

qibocal.auto.execute module#

Tasks execution.

class qibocal.auto.execute.Executor(graph: ~qibocal.auto.graph.Graph, history: ~qibocal.auto.history.History, output: ~pathlib.Path, qubits: dict[typing.Union[str, int], qibolab.qubits.Qubit], platform: ~qibolab.platform.Platform, update: bool = True, head: ~typing.Optional[~qibocal.auto.runcard.Id] = None, pending: ~typing.Set[~qibocal.auto.runcard.Id] = <factory>)[source]#

Bases: object

Execute a tasks’ graph and tracks its history.

graph: Graph#

The graph to be executed.

history: History#

The execution history, with results and exit states.

output: Path#

Output path.

qubits: dict[Union[str, int], qibolab.qubits.Qubit]#

Qubits to be calibrated.

platform: Platform#

Qubits’ platform.

update: bool = True#

Runcard update mechanism.

head: Optional[Id] = None#

The current position.

pending: Set[Id]#

The branched off tasks, not yet executed.

classmethod load(card: Runcard, output: Path, platform: Optional[Platform] = None, qubits: Optional[dict[Union[str, int], qibolab.qubits.Qubit]] = None, update: bool = True)[source]#

Load execution graph and associated executor from a runcard.

available(task: Task)[source]#

Check if a task has all dependencies satisfied.

successors(task: Task)[source]#

Retrieve successors of a specified task.

next() Optional[Id][source]#

Resolve the next task to be executed.

Returns None if the execution is completed.

property current#

Retrieve current task, associated to the head pointer.

run()[source]#

Actual execution.

The platform’s update method is called if: - self.update is True and task.update is None - task.update is True

qibocal.auto.graph module#

Execution graph and navigation utilities.

class qibocal.auto.graph.Graph(incoming_graph_data=None, **attr)[source]#

Bases: DiGraph

Execution graph.

classmethod load(actions: list[dict])[source]#

Load graph from list of actions dump.

Useful to load the graph from its description in a runcard.

classmethod from_actions(actions: list[qibocal.auto.runcard.Action])[source]#

Load graph from list of actions.

One node is added to the graph for each action, and the edges are created to represent the execution normal flow, according to the action.main and action.next attributes.

property start: Id#

Retrieve the graph starting point.

Note that this method is potentially unsafe, since it is not checking for the existence of multiple starting points (defined by a node.priority == 0 condition), and trust the graph to be a valid one.

To validate a graph for a single starting point check qibocal.auto.validate.starting_point().

task(id: Id) Task[source]#

Retrieve a task from its identifier.

tasks()[source]#

Iterate over all tasks in the graph.

qibocal.auto.history module#

Track execution history.

class qibocal.auto.history.Completed(task: Task, status: Status, folder: Path, _data: Optional[Data] = None, _results: Optional[Results] = None)[source]#

Bases: object

A completed task.

task: Task#

A snapshot of the task when it was completed.

status: Status#

Protocol status.

folder: Path#

Folder with data and results.

property datapath#

Path contaning data and results file for task.

property results#

Access task’s results.

property data#

Access task’s data.

class qibocal.auto.history.History[source]#

Bases: dict[tuple[Id, int], Completed]

Execution history.

This is not only used for logging and debugging, but it is an actual part of the execution itself, since later routines can retrieve the output of former ones from here.

push(completed: Completed)[source]#

Adding completed task to history.

qibocal.auto.operation module#

qibocal.auto.operation.OperationId#

Identifier for a calibration routine.

alias of str

qibocal.auto.operation.ParameterValue#

Valid value for a routine and runcard parameter.

alias of Union[float, int]

qibocal.auto.operation.Qubits#

Convenient way of passing qubit pairs in the routines.

qibocal.auto.operation.DATAFILE = 'data.npz'#

Name of the file where data acquired (arrays) by calibration are dumped.

qibocal.auto.operation.JSONFILE = 'conf.json'#

Name of the file where data acquired (global configuration) by calibration are dumped.

qibocal.auto.operation.RESULTSFILE = 'results.json'#

Name of the file where results are dumped.

qibocal.auto.operation.show_logs(func)[source]#

Decorator to add logs.

class qibocal.auto.operation.Parameters[source]#

Bases: object

Generic action parameters.

Implement parameters as Algebraic Data Types (similar to), by subclassing this marker in actual parameters specification for each calibration routine.

The actual parameters structure is only used inside the routines themselves.

nshots: int#

Number of executions on hardware

relaxation_time: float#

Wait time for the qubit to decohere back to the gnd state

classmethod load(parameters)[source]#

Load parameters from runcard.

Possibly looking into previous steps outputs.

class qibocal.auto.operation.Data[source]#

Bases: object

Data resulting from acquisition routine.

data: dict[typing.Union[tuple[typing.Union[str, int], int], str, int], numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]]#

Data object to store arrays

property qubits#

Access qubits from data structure.

property pairs#

Access qubit pairs ordered alphanumerically from data structure.

property global_params_dict#

Convert non-arrays attributes into dict.

save(path)[source]#

Store results.

to_npz(path)[source]#

Helper function to use np.savez while converting keys into strings.

to_json(path)[source]#

Helper function to dump to json in JSONFILE path.

class qibocal.auto.operation.Results[source]#

Bases: object

Generic runcard update.

As for the case of Parameters the explicit structure is only useful to fill the specific update, but in this case there should be a generic way

Each field might be annotated with an update metadata field, in order to mark them for later use in the runcard:

@dataclass
class Cmd1Res(Results):
    res: str = field(metadata=dict(update="myres"))
    num: int
property update: dict[str, Union[float, int]]#

Produce an update from a result object.

This is later used to update the runcard.

save(path)[source]#

Store results to json.

class qibocal.auto.operation.Routine(acquisition: Callable[[_ParametersT], _DataT], fit: Optional[Callable[[_DataT], _ResultsT]] = None, report: Optional[Callable[[_DataT, _ResultsT], None]] = None)[source]#

Bases: Generic[_ParametersT, _DataT, _ResultsT]

A wrapped calibration routine.

acquisition: Callable[[_ParametersT], _DataT]#

Data acquisition function.

fit: Callable[[_DataT], _ResultsT] = None#

Post-processing function.

report: Callable[[_DataT, _ResultsT], None] = None#

Plotting function.

property parameters_type#

Input parameters type.

property data_type#

“Data object type return by data acquisition.

property results_type#

“Results object type return by data acquisition.

property platform_dependent#

Check if acquisition involves platform.

property qubits_dependent#

Check if acquisition involves qubits.

class qibocal.auto.operation.DummyPars[source]#

Bases: Parameters

Dummy parameters.

class qibocal.auto.operation.DummyData[source]#

Bases: Data

Dummy data.

save(path)[source]#

Dummy method for saving data

class qibocal.auto.operation.DummyRes[source]#

Bases: Results

Dummy results.

qibocal.auto.operation.dummy_operation = Routine(acquisition=<function _dummy_acquisition>, fit=<function _dummy_fit>, report=<function _dummy_report>)#

Example of a dummy operation.

qibocal.auto.runcard module#

Specify runcard layout, handles (de)serialization.

qibocal.auto.runcard.Id#

Action identifiers type.

alias of str

class qibocal.auto.runcard.Action(id: ~qibocal.auto.runcard.Id, operation: ~typing.Optional[~qibocal.auto.operation.OperationId] = None, main: ~typing.Optional[~qibocal.auto.runcard.Id] = None, next: ~typing.Optional[~typing.Union[list[qibocal.auto.runcard.Id], ~qibocal.auto.runcard.Id]] = None, priority: ~typing.Optional[int] = None, qubits: ~typing.Union[list[typing.Union[str, int]], list[tuple[typing.Union[str, int], typing.Union[str, int]]]] = FieldInfo(default=PydanticUndefined, default_factory=<class 'list'>, extra={}), update: bool = True, parameters: ~typing.Optional[dict[str, typing.Any]] = None)[source]#

Bases: object

Action specification in the runcard.

id: Id#

Action unique identifier.

operation: Optional[OperationId] = None#

Operation to be performed by the executor.

main: Optional[Id] = None#

Main subsequent for action in normal flow.

next: Optional[Union[list[qibocal.auto.runcard.Id], Id]] = None#

Alternative subsequent actions, branching from the current one.

priority: Optional[int] = None#

Priority level, determining the execution order.

qubits: Union[list[Union[str, int]], list[tuple[Union[str, int], Union[str, int]]]] = FieldInfo(default=PydanticUndefined, default_factory=<class 'list'>, extra={})#

Local qubits (optional).

update: bool = True#

Runcard update mechanism.

parameters: Optional[dict[str, Any]] = None#

Input parameters, either values or provider reference.

class qibocal.auto.runcard.Runcard(actions: list[qibocal.auto.runcard.Action], qubits: Union[list[Union[str, int]], list[tuple[Union[str, int], Union[str, int]]]], backend: str = 'qibolab', platform: str = 'dummy')[source]#

Bases: object

Structure of an execution runcard.

actions: list[qibocal.auto.runcard.Action]#
qubits: Union[list[Union[str, int]], list[tuple[Union[str, int], Union[str, int]]]]#
backend: str = 'qibolab'#
platform: str = 'dummy'#
property backend_obj: Backend#

Allocate backend.

property platform_obj: Platform#

Allocate platform.

classmethod load(params: dict)[source]#

Load a runcard (dict).

qibocal.auto.status module#

Describe the status of a completed task.

Simple and general statuses are defined here, but more of them can be defined by individual calibrations routines, and user code as well:

class PinkFirst(Status):
    '''Follow the pink arrow as the next one.'''

@dataclass
class ParametrizedException(Status):
    '''Trigger exceptional workflow, passing down a further parameter.

    Useful if the handler function is using some kind of threshold, or can
    make somehow use of the parameter to decide, but in a way that is not
    completely established, so it should not be hardcoded in the status
    type.

    '''
    myvalue: int

@dataclass
class ExceptionWithInput(Status):
    '''Pass to next routine as input.'''
    routine_x_input: float

In general, statuses can encode a predetermined decision about what to do next, so the decision has been handled by the fitting function, or an open decision, that is left up to the handler function.

class qibocal.auto.status.Status[source]#

Bases: object

The exit status of a calibration routine.

class qibocal.auto.status.Normal[source]#

Bases: Status

All green.

class qibocal.auto.status.Broken[source]#

Bases: Status

Unrecoverable.

qibocal.auto.task module#

Action execution tracker.

qibocal.auto.task.MAX_PRIORITY = 1000000000#

A number bigger than whatever will be manually typed. But not so insanely big not to fit in a native integer.

qibocal.auto.task.TaskId#

Unique identifier for executed tasks.

class qibocal.auto.task.Task(action: qibocal.auto.runcard.Action, iteration: int = 0, qubits: list[typing.Union[str, int]] = <factory>)[source]#

Bases: object

action: Action#

Action object parsed from Runcard.

iteration: int = 0#

Task iteration (to be used for the ExceptionalFlow).

qubits: list[Union[str, int]]#

Local qubits.

property id: Id#

Task Id.

property uid: tuple[qibocal.auto.runcard.Id, int]#

Task unique Id.

property operation#

Routine object from Operation Enum.

property main#

Main node to be executed next.

property next: list[qibocal.auto.runcard.Id]#

Node unlocked after the execution of this task.

property priority#

Priority level.

property parameters#

Inputs parameters for self.operation.

property update#

Local update parameter.

run(platform: Platform, qubits: Union[dict[Union[str, int], qibolab.qubits.Qubit], dict[tuple[Union[str, int], Union[str, int]], qibolab.qubits.Qubit]]) Iterator[Union[Data, Results]][source]#

Generator functions for data acquisition and fitting:

Parameters
  • platform (Platform) – Qibolab’s platform

  • qubits (Union[Qubits, QubitsPairs]) – Qubit or QubitPairs dict.

Yields

data (Data) – data acquisition output results (`Results): data fitting output.

qibocal.auto.validate module#

Extra tools to validate an execution graph.

qibocal.auto.validate.starting_point(graph: Graph)[source]#

Check graph starting point.

Since a graph is designed to work with a unique starting point, the user has to make sure to specify a single one, since the starting point is identified only by a 0 priority (i.e. top-priority).

The execution of a graph with multiple starting points has to be considered undefined behavior.