-
Notifications
You must be signed in to change notification settings - Fork 14
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
Kernel class #758
Kernel class #758
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #758 +/- ##
==========================================
+ Coverage 63.86% 63.97% +0.10%
==========================================
Files 47 49 +2
Lines 5756 5773 +17
==========================================
+ Hits 3676 3693 +17
Misses 2080 2080
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Jacfomg.
Apart from some minor changes this PR should be ready to merge.
src/qibolab/serialize.py
Outdated
single_qubit = runcard["characterization"]["single_qubit"] | ||
for qubit in qubits.values(): | ||
qubit.kernel_path = extras_folder / single_qubit[qubit.name]["kernel_path"] | ||
kernels = Kernels.load(path=extras_folder / "kernels.npz") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would define "kernels.npz" above a top level variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using it I found here that I would like
Kernels(kernels).dump(Path(__file__).parent / "dummy" / KERNELS_FILE)
to be something like
Kernels(kernels).dump(Path(__file__).parent / platform.name / KERNELS_FILE)
but for some reason we it can be named "dummy"
or "dummy_couplers"
should we join them ?
src/qibolab/serialize.py
Outdated
single_qubit = runcard["characterization"]["single_qubit"] | ||
for qubit in qubits.values(): | ||
qubit.kernel_path = extras_folder / single_qubit[qubit.name]["kernel_path"] | ||
kernels = Kernels.load(path=extras_folder / KERNELS_FILE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this stage extras_folder
is used only for the kernels. Why don't we accept the whole kernel path (including the file name) instead of hardcoding to "kernels.npz"
? Maybe I want to use a different name for my kernel file, or play with different kernel files for the same platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's really a matter of taste.
But you can do the things you asked even with the current strategy. Just have multiple kernel files inside the extras_folder
, and rename those to kernels.npz
.
About the idea of replacing a folder with a file, since there is nothing else, in general I'd agree with you. But here it would be already better to have a single file per runcard (to avoid spreading them), and we start from two (the .py
and .yml
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I have a counterproposal: what if we keep the directory, but we move all the files in there?
I.e.
iqm5q/
platform.py
parameters.yml
kernels.npz
At least it would be easy to collect all the related files, and in case you want to preserve/circulate a platform, you could always tar
/zip
the folder and grab it as a single file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seemed more future proof as we may need more stuff to be in that folder, and also what @alecandido mentioned would be more organized so we can do it on another PR on the qrc_cluster platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iqm5q/ platform.py parameters.yml kernels.npz
In my opinion, this is the best solution, but I agree doing it in another PR because it requires a few more changes which are unrelated to the kernels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alecandido @stavros11 @Jacfomg if everyone agrees I can open a PR in qibocal to generate directly folders and not just platform runcards. I believe that it should be feasible. It should be useful for the qibocal user to be able to see directly the create_function alongside the parameters and the kernels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it would be useful. I would just wait to do it after we implement the structure proposed above (one directory per platform) in qibolab and in the platforms. Also, I think it makes more sense to implement the function you are proposing in qibolab, perhaps replacing the current dump_runcard
and just use it qibocal, because at the end of the day it solves the problem of platform serialization which is a qibolab problem. However, this is a bit orthogonal to #762, so let’s wait to see what others think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. The function should be in qibolab. I will wait.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you that we should try to roll it out, and we should try to do it in Qibolab.
Btw, if it's going through Qibolab it should be also a non-breaking change, since Qibocal should not care much about the runcard serialization structure.
However, this is a bit orthogonal to #762, so let’s wait to see what others think.
I would say orthogonal is the correct word, not opposite. The moment we implement the folder, we could well dump the parameters in JSON, and drop the PyYAML dependency as well.
src/qibolab/serialize.py
Outdated
if qubit.kernel is not None: | ||
kernels[qubit.name] = qubit.kernel | ||
qubit.kernel = None | ||
Kernels(kernels).dump(Path(__file__).parent / "dummy" / KERNELS_FILE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method is used by all platforms. Why are we always dumping in the directory of the dummy?
I think this point requires some discussion. If you want to always dump the kernels in the file you loaded them from, it is probably convenient to make path
an attribute of Kernels
instead of passing it seperately to load
and dump
. But I am not sure if we always want to overwrite kernels during calibration. If no, we need a different mechanism to pass the the path to dump to, which will also be exposed to qibocal (and the user).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two reasons, the first I forgot and the second it's related to this. #758 (comment) I wanted to use the platform.name
but the dummy has two, I think the best would be something like this ?
name = platform.name
if platform.name == "dummy_couplers":
name = "dummy"
Kernels(kernels).dump(Path(__file__).parent / name / KERNELS_FILE)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For as long as we need to maintain two dummy platforms, couldn't we have actually two folders?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not that much concerned about the dummy, the implemented solution should be fine. However, this is still a bit problematic because it is asymmetric to the loading.
If I understand it correctly, when you create the platform you will load the kernels from whatever extras_folder
is passed to load_qubits
. This is typically located together with the platform runcard. Then when you (or qibocal) call dump
it is using Path(__file__).parent / name
to determine the directory, where __file__
is the serialize.py. Therefore it will dump the new kernels inside your qibolab installation, which is in general a different place than where the runcards are stored. Is this what we want?
More info: I understand this works okay for the dummy, but did you try it with other platforms, eg. iqm5q?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the other solution, I'm fine with any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want that for the dummy, but not for the other platforms. I will think of something then. We would need the extras_folder or something in qibocal as well to dump the kernels properly, any suggestions ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think dump_runcard
is automatically called by qibocal after every routine. So if you add kernels to any platform (eg. iqm5q) and you run any qibocal routine, after execution it will try to dump the "new" kernels to a directory like
qibolab/src/qibolab/iqm5q/kernels.npz
and will probably fail if there is no folder iqm5q
within qibolab. At least that's what I think, I didn't do the actual test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are failing because of that, can I add the extras_folder path as a atribute for the platform ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s probably acceptable for now and we can improve once we implement the folder structure proposed by @alecandido.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we could go incrementally (eventually we can even use an env var, or even better the same variable we use to locate the runcards).
qibolab/src/qibolab/__init__.py
Line 21 in 3416a8e
def get_platforms_path(): |
However, for dummy we should mock the serialization, even when deployed: the installation folder might require privileges that the user does not have.
Furthermore, I start considering the option to split dummy from the regular Qibolab (we could not implement just in tests/
because it's being used also by Qibocal... I'm thinking...)
@Jacfomg could you also merge/rebase on |
I definitely agree with this @stavros11 here #758 (comment), and it's sensible to address also the other comments. But concerning the rest, I have nothing else to amend. Once solved and rebased, you could merge (I could give a further approval, but since I'd wait for the comments above, I'll leave the pleasure to @stavros11). |
@stavros11 I implemented the folders approach discussed here:
If you approve it I will open the corresponding PR in |
First we'd need to have a PR for that in Qibolab ;) (you could start from there if you wish) Internal names are up for discussion... |
Btw, as @stavros11 pointed out above, this is orthogonal to #762 in a certain sense, since they are two separate changes. |
I've just implemented it here in this PR :) |
Ah, I didn't notice 0351323 |
@andrea-pasquale I would say names are up for discussion, but I'd avoid using the folder name for internal names. If we choose something, you won't need to know anything beyond the folder: after that, all we be loaded in the same way. I know it's now a minimal difference, because the only function resolving the internal names is the same one receiving the path. But it's more decoupled if you do not require them to be the same (e.g. you could just rename the folder, without renaming any file inside). |
If I understood correctly since all that matters is the path to the folder every file inside the folder can be standardized, correct? iqm5q/
platform.py
parameters.yml
kernels.npz Since I was just moving files around I forgot to think about using standardized names. |
Indeed. I wanted to point out that I'm not particularly keen on those names, for as long as we pick some standardized names. |
Great, so I understood correctly. |
I didn't really follow the discussion related to #762. The plan is to switch from |
In Qibolab YAML is used in a single place, a runcard that should not be manually written.
A few notes in advance: for when you need to write manually, it's not difficult to convert to YAML and convert back: from pathlib import Path
import json
import sys
import yaml
path = Path(sys.argv[1])
d = json.loads(path.load_text())
path.write_text(yaml.dumps(d)) and forth (swap We could make a minimal CLI in a separate package (distributed together, with dependencies as extras - or even distributed separately, or not at all, if it's simpler and enough), named |
Co-authored-by: Alessandro Candido <[email protected]>
for more information, see https://pre-commit.ci
Partial port from #782
src/qibolab/serialize.py
Outdated
def dump_kernels(platform: Platform, path: Path): | ||
"""Creates Kernels instance from platform and dumps as npz. | ||
|
||
Args: | ||
platform (qibolab.platform.Platform): The platform to be serialized. | ||
path (pathlib.Path): Path that the kernels file will be saved. | ||
""" | ||
|
||
# create and dump kernels | ||
kernels = Kernels() | ||
for qubit in platform.qubits.values(): | ||
if qubit.kernel is not None: | ||
kernels[qubit.name] = qubit.kernel | ||
|
||
kernels.dump(path / KERNELS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For even better isolation, eventually I'd consider having these functions just writing on byte streams, and returning them.
The top level dump could be the one responsible to attribute each byte stream a path, and dump it there.
In any case, it's not for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The drawback of byte streams is just memory consumption: if you dump on streams, instead of directly on disk, you double the amount of memory you consume.
But I'd say CPU memory should not be an issue in Qibolab...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for isolating the conversion to JSON in #782 @alecandido
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @andrea-pasquale. Looks good to me, other than some minor comments.
Even though it already has two approvals, the only thing before merging is that I’d open the corresponding PR in qibolab_platforms_qrc and try to test with some instruments (which I believe we haven’t done yet). Let me know if you’ll do that, otherwise I can also help rewriting the existing platforms to the new folder structure.
|
||
where ``platform.py`` contains instruments information, ``parameters.yml`` | ||
includes calibration parameters and ``kernels.npz`` is an optional | ||
file with additional calibration parameters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In principle, parameters.yml
is also optional, as someone can define the qubit/channel objects hardcoded in the create
. This is basically explained in the lab.rst
tutorial.
However, dumping the platform after will automatically create parameters, so I am not sure whether we should advocate this kind of usage.
src/qibolab/dummy/__init__.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could expose create_dummy
here to keep the same interface as before
from qibolab.dummy import create_dummy
@@ -29,32 +30,33 @@ def get_platforms_path(): | |||
return Path(profiles) | |||
|
|||
|
|||
def create_platform(name, runcard=None): | |||
def create_platform(name, path: Path = None) -> Platform: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the impression that the path
argument is no longer required here. Before it was used to link a YAML to the create (assuming you wanted to use different YAMLs for the same create?). But this is no longer valid given that we’re proposing a fixed folder structure.
However, this will become more clear once we try to define some actual platforms (eg in qibolab_platforms_qrc).
platform (qibolab.platform.Platform): The platform to be serialized. | ||
path (pathlib.Path): Path where yaml and npz will be dumped. | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn’t try to use this yet, but shouldn’t it:
- Create the folder specified by
path
if it doesn’t exist (given that it’ll try to write files inside) - Dump also
platform.py
inside this folder?
I’ll try to use and review this comment.
Co-authored-by: Stavros Efthymiou <[email protected]>
Thanks for the review @stavros11. |
src/qibolab/serialize.py
Outdated
if qubit.kernel is not None: | ||
kernels[qubit.name] = qubit.kernel | ||
|
||
kernels.dump(path / KERNELS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will not work. KERNELS
is appended to the path
twice, once here and once in
qibolab/src/qibolab/kernels.py
Line 37 in 5e46e6f
path / KERNELS, |
We should test the PRs better before considering to merge. Particularly the new dump_kernels
and dump_platform
methods, I believe are not captured by the tests, while they can be easily tested without access to instruments/QPUs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I also found the same error while trying to run tests in qibocal.
I will try to add tests to cover dump_platform
and dump_kernels
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests added in 8f49f89
Thanks @andrea-pasquale. I will merge this to unlock the CI in the platforms repo (and the change is already big). If you like to change |
Follows what discussed in #754. The only thing I removed the
kernel
from the qubit reprChecklist: