Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to ActionBuilder #271

Merged
merged 34 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6306c30
Moving and simplyfing methods
andrea-pasquale Mar 7, 2023
5a3bf03
Fix tests
andrea-pasquale Mar 8, 2023
cf33c76
Add forgotten file
andrea-pasquale Mar 8, 2023
37f683d
Remove try-except block
andrea-pasquale Mar 8, 2023
e8f3358
Fix plotting functions
andrea-pasquale Mar 8, 2023
00e5392
Minor fixes and enable qq-live for RB
andrea-pasquale Mar 9, 2023
6618fc8
Fix tests
andrea-pasquale Mar 10, 2023
cd71901
Merge branch 'main' into simplify_builder
andrea-pasquale Apr 11, 2023
af29b7b
vodovozovaliza Apr 28, 2023
0b075d5
Minor changes
vodovozovaliza Apr 28, 2023
52d3b13
Create fitting_report tables
vodovozovaliza Apr 28, 2023
8b1402e
Merge branch 'main' into simplify_builder
andrea-pasquale Apr 28, 2023
b85fdb6
Fix tests
vodovozovaliza Apr 29, 2023
6ed1edb
Merge branch 'simplify_builder' into nigsc_changes
vodovozovaliza May 1, 2023
17bd410
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 1, 2023
ea94088
nigsc
vodovozovaliza May 1, 2023
499a2af
Fix tests
vodovozovaliza May 1, 2023
d926f1d
Add suggestions
vodovozovaliza May 1, 2023
9391972
Fix warnings.
vodovozovaliza May 1, 2023
f6bcd1c
Minor changes
vodovozovaliza May 1, 2023
b028c51
main runcard | embed circuit better
wilkensJ May 1, 2023
5f4952d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 1, 2023
3c3823a
Improving nigsc plotting
wilkensJ May 2, 2023
59a93b5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 2, 2023
7588c4d
improve plot | fix coverage
vodovozovaliza May 3, 2023
6c5612c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2023
b21a5c3
Update src/qibocal/calibrations/niGSC/basics/experiment.py
vodovozovaliza May 3, 2023
02df578
Update src/qibocal/calibrations/niGSC/basics/experiment.py
vodovozovaliza May 3, 2023
1a2cf1c
Update src/qibocal/calibrations/niGSC/basics/experiment.py
vodovozovaliza May 3, 2023
f4416ec
Update src/qibocal/calibrations/niGSC/basics/experiment.py
vodovozovaliza May 3, 2023
12e587b
reverse table format
May 3, 2023
4277bad
Merge pull request #318 from qiboteam/nigsc_changes
andrea-pasquale May 3, 2023
cc265c8
Apply Liza' suggestions
andrea-pasquale May 8, 2023
1cdd8dd
Merge branch 'main' into simplify_builder
vodovozovaliza May 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from qibolab.pulses import PulseSequence

from qibocal import plots
from qibocal.config import raise_error
from qibocal.data import DataUnits
from qibocal.decorators import plot
from qibocal.fitting.methods import lorentzian_fit
Expand Down
38 changes: 31 additions & 7 deletions src/qibocal/calibrations/niGSC/XIdrb.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,23 @@ def build_report(experiment: Experiment, df_aggr: pd.DataFrame) -> Figure:

# Initiate a report object.
report = moduleReport()
fitting_report = ""
# Add general information to the object.
report.info_dict["Number of qubits"] = len(experiment.data[0]["samples"][0])
report.info_dict["Number of shots"] = len(experiment.data[0]["samples"])
report.info_dict["runs"] = experiment.extract("samples", "depth", "count")[1][0]
report.info_dict["Fitting daviations"] = "".join(
[
"{}:{:.3f} ".format(key, df_aggr.loc["filter"]["perr"][key])
for key in df_aggr.loc["filter"]["perr"]
]
)
report.info_dict[
"A1_real"
] = f"{df_aggr['popt_real'][0]['A1_real']:.3f} +/- {df_aggr['perr'][0]['A1_err']:.3f}"
report.info_dict[
"p1_real"
] = f"{df_aggr['popt_real'][0]['p1']:.3f} +/- {df_aggr['perr'][0]['p1_err']:.3f}"
report.info_dict[
"A2_real"
] = f"{df_aggr['popt_real'][0]['A2_real']:.3f} +/- {df_aggr['perr'][0]['A2_err']:.3f}"
report.info_dict[
"p2_real"
] = f"{df_aggr['popt_real'][0]['p2']:.3f} +/- {df_aggr['perr'][0]['p2_err']:.3f}"
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
# Use the predefined ``scatter_fit_fig`` function from ``basics.utils`` to build the wanted
# plotly figure with the scattered filtered data along with the mean for
# each depth and the exponential fit for the means.
Expand All @@ -229,5 +236,22 @@ def build_report(experiment: Experiment, df_aggr: pd.DataFrame) -> Figure:
experiment, df_aggr, "depth", "filter", fittingparam_label="popt_imag"
)
)
report.info_dict[
"A1_imag"
] = f"{df_aggr['popt_imag'][0]['A1_imag']:.3f} +/- {df_aggr['perr'][0]['A1_err']:.3f}"
report.info_dict[
"p1_imag"
] = f"{df_aggr['popt_imag'][0]['p1']:.3f} +/- {df_aggr['perr'][0]['p1_err']:.3f}"
report.info_dict[
"A2_imag"
] = f"{df_aggr['popt_imag'][0]['A2_imag']:.3f} +/- {df_aggr['perr'][0]['A2_err']:.3f}"
report.info_dict[
"p2_imag"
] = f"{df_aggr['popt_imag'][0]['p2']:.3f} +/- {df_aggr['perr'][0]['p2_err']:.3f}"
for key, value in report.info_dict.items():
if isinstance(value, str):
fitting_report += f"q{0}/r{0} | {key}: {value}<br>"
else:
fitting_report += f"q{0}/r{0} | {key}: {value:,.0f}<br>"
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
# Return the figure the report object builds out of all figures added to the report.
return report.build()
return report.build(), fitting_report
17 changes: 9 additions & 8 deletions src/qibocal/calibrations/niGSC/basics/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from qibo.models import Circuit
from qibo.noise import NoiseModel

from qibocal.calibrations.niGSC.basics.utils import copy_circuit, experiment_directory
from qibocal.calibrations.niGSC.basics.utils import copy_circuit
from qibocal.cli.utils import generate_output_folder
from qibocal.config import raise_error


Expand Down Expand Up @@ -88,8 +89,8 @@ def load(cls, path: str) -> Experiment:
Returns:
Experiment: The object with data (and circuitfactory).
"""
datapath = f"{path}experiment_data.pkl"
circuitspath = f"{path}circuits.pkl"
datapath = f"{path}/experiment_data.pkl"
circuitspath = f"{path}/circuits.pkl"
if isfile(datapath):
with open(datapath, "rb") as f:
data = pickle.load(f)
Expand All @@ -107,7 +108,7 @@ def load(cls, path: str) -> Experiment:
obj = cls(circuitfactory, data=data, nshots=nshots)
return obj

def save(self, path: str | None = None) -> str:
def save(self, path: str | None = None, force=False) -> str:
"""Creates a path if None given and pickles relevant data from ``self.data``
and if ``self.circuitfactory`` is a list that one too.

Expand All @@ -118,17 +119,17 @@ def save(self, path: str | None = None) -> str:
# Check if path to store is given, if not create one. If yes check if the last character
# is a /, if not add it.
if path is None:
self.path = experiment_directory("rb")
self.path = generate_output_folder(path, force)
else:
self.path = path if path[-1] == "/" else f"{path}/"
self.path = path
# Only if the circuit factory is a list it will be stored.
if isinstance(self.circuitfactory, list):
with open(f"{self.path}circuits.pkl", "wb") as f:
with open(f"{self.path}/circuits.pkl", "wb") as f:
pickle.dump(self.circuitfactory, f)
# And only if data is not None the data list (full of dicionaries) will be
# stored.
if self.data is not None:
with open(f"{self.path}experiment_data.pkl", "wb") as f:
with open(f"{self.path}/experiment_data.pkl", "wb") as f:
pickle.dump(self.data, f)
# It is convenient to know the path after storing, so return it.
return self.path
Expand Down
53 changes: 16 additions & 37 deletions src/qibocal/calibrations/niGSC/basics/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
from plotly.subplots import make_subplots

import qibocal.calibrations.niGSC.basics.fitting as fitting_methods
from qibocal.calibrations.niGSC.basics import utils
from qibocal.calibrations.niGSC.basics.experiment import Experiment
from qibocal.plots.utils import get_data_subfolders


def plot_qq(folder: str, routine: str, qubit, format):
fitting_report = ""
"""Load the module for which the plot has to be done.


Expand All @@ -25,15 +24,20 @@ def plot_qq(folder: str, routine: str, qubit, format):

import importlib

# Load the module, something like 'standardrb'.
module = importlib.import_module(f"qibocal.calibrations.niGSC.{routine}")
# Load the experiment with the class method ``load``.
experiment = module.ModuleExperiment.load(f"{folder}/data/{routine}/")
# In this data frame the precomputed fitting parameters and other
# parameters for fitting and plotting are stored.
aggr_df = pd.read_pickle(f"{folder}/data/{routine}/fit_plot.pkl")
# Build the figure/report using the responsible module.
plotly_figure = module.build_report(experiment, aggr_df)
subfolders = get_data_subfolders(folder)
report_n = 0
for subfolder in subfolders:
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
# Load the module, something like 'standardrb'.
module = importlib.import_module(f"qibocal.calibrations.niGSC.{routine}")
# Load the experiment with the class method ``load``.
experiment = module.ModuleExperiment.load(f"{folder}/{subfolder}/{routine}/")
# In this data frame the precomputed fitting parameters and other
# parameters for fitting and plotting are stored.
aggr_df = pd.read_pickle(f"{folder}/data/{routine}/fit_plot.pkl")
# Build the figure/report using the responsible module.
plotly_figure, fitting_report = module.build_report(experiment, aggr_df)
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved

report_n += 1
andrea-pasquale marked this conversation as resolved.
Show resolved Hide resolved
return [plotly_figure], fitting_report


Expand Down Expand Up @@ -66,24 +70,6 @@ def build(self):
plot, row=count // divide_by + 1, col=count % divide_by + 1
)

fig.add_annotation(
dict(
bordercolor="black",
font=dict(color="black", size=16),
x=0.0,
y=1.0 / (int(l / divide_by) + l % divide_by + 1)
- len(self.info_dict) * 0.005,
showarrow=False,
text="<br>".join(
[f"{key} : {value}\n" for key, value in self.info_dict.items()]
),
align="left",
textangle=0,
yanchor="top",
xref="paper",
yref="paper",
)
)
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
fig.update_xaxes(title_font_size=18, tickfont_size=16)
fig.update_yaxes(title_font_size=18, tickfont_size=16)
fig.update_layout(
Expand Down Expand Up @@ -148,14 +134,7 @@ def scatter_fit_fig(
go.Scatter(
x=x_fit,
y=y_fit,
name="".join(
[
"{}:{} ".format(
key, utils.number_to_str(dfrow[fittingparam_label][key])
)
for key in dfrow[fittingparam_label]
]
),
name="Fit",
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
line=go.scatter.Line(dash="dot"),
)
)
Expand Down
30 changes: 0 additions & 30 deletions src/qibocal/calibrations/niGSC/basics/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,6 @@
ONEQ_GATES = ["I", "X", "Y", "Z", "H", "S", "SDG", "T", "TDG"]


def experiment_directory(name: str):
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
"""Make the directory where the experiment will be stored."""
from datetime import datetime

overall_dir = "experiments/"
# Check if the overall directory exists. If not create it.
if not isdir(overall_dir):
mkdir(overall_dir)
# Get the current date and time.
dt_string = datetime.now().strftime("%y%b%d_%H%M%S")
# Every script name ``name`` gets its own directory.
subdirectory = f"{overall_dir}{name}/"
if not isdir(subdirectory): # pragma: no cover
mkdir(subdirectory)
# Name the final directory for this experiment.
final_directory = f"{subdirectory}experiment{dt_string}/"
if not isdir(final_directory): # pragma: no cover
mkdir(final_directory)
else:
already_file, count = True, 1
while already_file:
final_directory = f"{subdirectory}experiment{dt_string}_{count}/"
if not isdir(final_directory):
mkdir(final_directory)
already_file = False
else:
count += 1
return final_directory


def effective_depol(error_channel, **kwargs):
""" """
liouvillerep = error_channel.to_pauli_liouville(normalize=True)
Expand Down
24 changes: 16 additions & 8 deletions src/qibocal/calibrations/niGSC/simulfilteredrb.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,23 +211,31 @@ def build_report(experiment: Experiment, df_aggr: pd.DataFrame) -> Figure:

# Initiate a report object.
report = moduleReport()
fitting_report = ""
# Add general information to the object.
report.info_dict["Number of qubits"] = len(experiment.data[0]["samples"][0])
report.info_dict["Number of shots"] = len(experiment.data[0]["samples"])
report.info_dict["runs"] = experiment.extract("samples", "depth", "count")[1][0]
lambdas = iter(product([0, 1], repeat=int(report.info_dict["Number of qubits"])))
for kk, l in enumerate(lambdas):
# Add the fitting errors which will be displayed in a box under the plots.
report.info_dict[f"Fitting daviations irrep {l}"] = "".join(
[
"{}:{:.3f} ".format(key, df_aggr.loc[f"irrep{kk}"]["perr"][key])
for key in df_aggr.loc[f"irrep{kk}"]["perr"]
]
)
report.info_dict[
f"A Irrep{kk} "
] = f"{df_aggr.loc[f'irrep{kk}']['popt']['A']:.3f} +/- {df_aggr.loc[f'irrep{kk}']['perr']['A_err']:.3f}"
report.info_dict[
f"p Irrep{kk}"
] = f"{df_aggr.loc[f'irrep{kk}']['popt']['p']:.3f} +/- {df_aggr.loc[f'irrep{kk}']['perr']['p_err']:.3f}"

wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
# Use the predefined ``scatter_fit_fig`` function from ``basics.utils`` to build the wanted
# plotly figure with the scattered filter function points and then mean per depth.
figdict = scatter_fit_fig(experiment, df_aggr, "depth", f"irrep{kk}")
# Add a subplot title for each irrep.
figdict["subplot_title"] = f"Irrep {l}"
figdict["subplot_title"] = f"Irrep {l[0]}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The irrep l is a bit string showing the projectors which are used for this plot. If there are three qubits, each bit in for example l=(0,1,0) tells now where the projector was trivial (=0) and adjoint (=1), meaning taking the first entry will not display this information correctly.
In short: this change should be reversed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is still not right, sorry I did not see that in the previous PR.

andrea-pasquale marked this conversation as resolved.
Show resolved Hide resolved
report.all_figures.append(figdict)
return report.build()

for key, value in report.info_dict.items():
if isinstance(value, str):
fitting_report += f"q{0}/r{0} | {key}: {value}<br>"
else:
fitting_report += f"q{0}/r{0} | {key}: {value:,.0f}<br>"
return report.build(), fitting_report
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
24 changes: 17 additions & 7 deletions src/qibocal/calibrations/niGSC/standardrb.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,15 @@ def build_report(experiment: Experiment, df_aggr: pd.DataFrame) -> Figure:
report.info_dict["Number of qubits"] = len(experiment.data[0]["samples"][0])
report.info_dict["Number of shots"] = len(experiment.data[0]["samples"])
report.info_dict["runs"] = experiment.extract("samples", "depth", "count")[1][0]
report.info_dict["Fitting daviations"] = "".join(
[
"{}:{:.3f} ".format(key, df_aggr.iloc[0]["perr"][key])
for key in df_aggr.iloc[0]["perr"]
]
)
report.info_dict[
"A"
] = f"{df_aggr['popt'][0]['A']:.3f} +/- {df_aggr['perr'][0]['A_err']:.3f}"
report.info_dict[
"p"
] = f"{df_aggr['popt'][0]['p']:.3f} +/- {df_aggr['perr'][0]['p_err']:.3f}"
report.info_dict[
"B"
] = f"{df_aggr['popt'][0]['B']:.3f} +/- {df_aggr['perr'][0]['B_err']:.3f}"
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
report.info_dict["Gate fidelity"] = "{:.4f}".format(
gate_fidelity(df_aggr.iloc[0]["popt"]["p"])
)
Expand All @@ -217,5 +220,12 @@ def build_report(experiment: Experiment, df_aggr: pd.DataFrame) -> Figure:
report.all_figures.append(
scatter_fit_fig(experiment, df_aggr, "depth", "groundstate probability")
)

fitting_report = ""
for key, value in report.info_dict.items():
if isinstance(value, str):
fitting_report += f"q{0}/r{0} | {key}: {value}<br>"
else:
fitting_report += f"q{0}/r{0} | {key}: {value:,.0f}<br>"
wilkensJ marked this conversation as resolved.
Show resolved Hide resolved
# Return the figure the report object builds out of all figures added to the report.
return report.build()
return report.build(), fitting_report
12 changes: 8 additions & 4 deletions src/qibocal/cli/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ def update_meta(metadata, metadata_new):
metadata["backend"] = metadata["backend"] + " , " + metadata_new["backend"]
metadata["date"] = metadata["date"] + " , " + metadata_new["date"]
metadata["end-time"] = metadata["end-time"] + " , " + metadata_new["end-time"]
metadata["platform"] = metadata["platform"] + " , " + metadata_new["platform"]
if "platform" in metadata:
metadata["platform"] = metadata["platform"] + " , " + metadata_new["platform"]
metadata["start-time"] = metadata["start-time"] + " , " + metadata_new["start-time"]
metadata["title"] = metadata["title"] + " , " + metadata_new["title"]
metadata["versions"]["numpy"] = (
Expand All @@ -283,9 +284,12 @@ def update_meta(metadata, metadata_new):
metadata["versions"]["qibocal"] = (
metadata["versions"]["qibocal"] + " , " + metadata_new["versions"]["qibocal"]
)
metadata["versions"]["qibolab"] = (
metadata["versions"]["qibolab"] + " , " + metadata_new["versions"]["qibolab"]
)
if "qibolab" in metadata["versions"]:
metadata["versions"]["qibolab"] = (
metadata["versions"]["qibolab"]
+ " , "
+ metadata_new["versions"]["qibolab"]
)
with open(f"{TARGET_COMPARE_DIR}/meta.yml", "w") as file:
yaml.safe_dump(metadata, file)

Expand Down
Loading