Skip to content

Commit

Permalink
fix: Attempt to solve #919
Browse files Browse the repository at this point in the history
  • Loading branch information
andrea-pasquale committed Feb 19, 2025
1 parent 5520bba commit ba78e81
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 41 deletions.
11 changes: 9 additions & 2 deletions src/qibocal/auto/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,19 @@ def run_protocol(
protocol: Routine,
parameters: Action,
mode: ExecutionMode = AUTOCALIBRATION,
output: Optional[Path] = None,
) -> Completed:
"""Run single protocol in ExecutionMode mode."""
task = Task(action=parameters, operation=protocol)
log.info(f"Executing mode {mode} on {task.action.id}.")

completed = task.run(platform=self.platform, targets=self.targets, mode=mode)
completed = task.run(
platform=self.platform,
targets=self.targets,
mode=mode,
folder=self.history.task_path(
self.history._pending_task_id(task.id), output
),
)
self.history.push(completed)

# TODO: drop, as the conditions won't be necessary any longer, and then it could
Expand Down
19 changes: 13 additions & 6 deletions src/qibocal/auto/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,30 @@ def load(cls, path: Path):
instance.push(Completed.load(protocol))
return instance

def _pending_task_id(self, _id: Id) -> TaskId:
"""Retrieve the TaskId of a given task."""
return TaskId(id=_id, iteration=len(self._tasks[_id]))

def _executed_task_id(self, _id: Id) -> TaskId:
"""Retrieve the TaskId of a given task."""
return TaskId(id=_id, iteration=len(self._tasks[_id]) - 1)

def push(self, completed: Completed) -> TaskId:
"""Adding completed task to history."""
id = completed.task.id
self._tasks[id].append(completed)
task_id = TaskId(id=id, iteration=len(self._tasks[id]) - 1)
task_id = self._executed_task_id(id)
self._order.append(task_id)
return task_id

@staticmethod
def route(task_id: TaskId, folder: Path) -> Path:
def task_path(self, task_id: TaskId, folder: Optional[Path]) -> Path:
"""Determine the path related to a completed task given TaskId.
`folder` should be usually the general output folder, used by Qibocal to store
all the execution results. Cf. :class:`qibocal.auto.output.Output`.
"""
if folder is None:
return None
return folder / "data" / f"{task_id}"

def flush(self, output: Optional[Path] = None):
Expand All @@ -97,9 +106,7 @@ def flush(self, output: Optional[Path] = None):
Specifying `output` is possible to select which folder should be considered as
the general Qibocal output folder. Cf. :class:`qibocal.auto.output.Output`.
"""
for task_id, completed in self.items():
if output is not None:
completed.path = self.route(task_id, output)
for _, completed in self.items():
completed.flush()

# TODO: implement time_travel()
Expand Down
14 changes: 7 additions & 7 deletions src/qibocal/auto/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,7 @@ def dump(self, path: Path):
self._export_stats()
(path / META).write_text(json.dumps(self.meta.dump(), indent=4))

# dump tasks
self.history.flush(path)
self.history.flush()

# update platform
if self.platform is not None:
Expand Down Expand Up @@ -247,13 +246,14 @@ def process(
and completed.results is not None
):
raise KeyError(f"{task_id} already contains fitting results.")

# TODO: this is a plain hack, to be fixed together with the task lifecycle
# refactor
self.history._tasks[task_id.id][task_id.iteration] = completed.task.run(
platform=self.platform, mode=mode, folder=completed.path
platform=self.platform,
mode=mode,
folder=self.history.task_path(
self.history._executed_task_id(task_id.id), output
),
)
self.history.flush(output)

self.history.flush()
if update and completed.task.update:
completed.update_platform(platform=self.platform)
3 changes: 2 additions & 1 deletion src/qibocal/auto/runcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def run(
protocol=getattr(protocols, action.operation),
parameters=action,
mode=mode,
output=output,
)
instance.history.flush(output)
history.flush()
return instance.history
28 changes: 15 additions & 13 deletions src/qibocal/auto/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ def run(
self.action.targets = targets

completed = Completed(self, folder)

try:
if platform is not None:
if self.parameters.nshots is None:
Expand All @@ -153,21 +152,21 @@ def run(
except (RuntimeError, AttributeError):
operation = dummy_operation
parameters = DummyPars()

if ExecutionMode.ACQUIRE in mode:
if operation.platform_dependent and operation.targets_dependent:
completed.data, completed.data_time = operation.acquisition(
parameters,
platform=platform,
targets=self.targets,
)

else:
completed.data, completed.data_time = operation.acquisition(
parameters, platform=platform
)
completed.dump()
if ExecutionMode.FIT in mode:
completed.results, completed.results_time = operation.fit(completed.data)
completed.dump()
return completed


Expand Down Expand Up @@ -223,19 +222,22 @@ def results(self, value):

def dump(self):
"""Dump object to disk."""
if self.path is None:
raise ValueError("No known path where to dump execution results.")

self.path.mkdir(parents=True, exist_ok=True)
self.task.dump(self.path)
if self._data is not None:
self._data.save(self.path)
if self._results is not None:
self._results.save(self.path)
if self.path is not None:
self.path.mkdir(parents=True, exist_ok=True)
# make sure to dump only once
if not (self.path / SINGLE_ACTION).exists():
self.task.dump(self.path)
if self._data is not None:
if self.task.operation.data_type.load(self.path) is None:
self._data.save(self.path)
if (
self.task.operation.results_type.load(self.path) is None
and self._results is not None
):
self._results.save(self.path)

def flush(self):
"""Dump disk, and release from memory."""
self.dump()
self._data = None
self._results = None

Expand Down
4 changes: 2 additions & 2 deletions src/qibocal/protocols/resonator_spectroscopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ class ResonatorSpectroscopyData(Data):
will apply a minus to the phase data."""
data: dict[QubitId, npt.NDArray[ResSpecType]] = field(default_factory=dict)
"""Raw data acquired."""
power_level: Optional[PowerLevel] = None
power_level: Optional[PowerLevel] = PowerLevel.low
"""Power regime of the resonator."""

@classmethod
def load(cls, path):
obj = super().load(path)
# Instantiate PowerLevel object
if obj.power_level is not None: # pylint: disable=E1101
if hasattr(obj, "power_level"): # pylint: disable=E1101
obj.power_level = PowerLevel(obj.power_level) # pylint: disable=E1101
return obj

Expand Down
9 changes: 5 additions & 4 deletions src/qibocal/protocols/state_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ def save(self, path):

@classmethod
def load(cls, path):
circuit = Circuit.from_dict(json.loads((path / CIRCUIT_PATH).read_text()))
data = super().load_data(path, DATAFILE)
params = super().load_params(path, DATAFILE)
return cls(data=data, circuit=circuit, targets=params["targets"])
if (path / CIRCUIT_PATH).exists():
circuit = Circuit.from_dict(json.loads((path / CIRCUIT_PATH).read_text()))
data = super().load_data(path, DATAFILE)
params = super().load_params(path, DATAFILE)
return cls(data=data, circuit=circuit, targets=params["targets"])


@dataclass
Expand Down
11 changes: 6 additions & 5 deletions src/qibocal/protocols/two_qubit_state_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ def save(self, path):

@classmethod
def load(cls, path):
return cls(
data=super().load_data(path, DATAFILE),
ideal=super().load_data(path, SIMULATED_DENSITY_MATRIX),
simulated=QuantumState.load(path / "simulated.json"),
)
if (path / "simulated.json").exists():
return cls(
data=super().load_data(path, DATAFILE),
ideal=super().load_data(path, SIMULATED_DENSITY_MATRIX),
simulated=QuantumState.load(path / "simulated.json"),
)


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def fake_output(tmp_path: Path) -> tuple[Output, Path]:
executor = Executor(
history=History(), targets=list(platform.qubits), platform=platform
)
executor.run_protocol(flipping, ACTION, mode=ExecutionMode.ACQUIRE)
executor.run_protocol(flipping, ACTION, mode=ExecutionMode.ACQUIRE, output=tmp_path)
meta.end()
platform.disconnect()
output.history = executor.history
Expand Down

0 comments on commit ba78e81

Please sign in to comment.