From ec9531f3ae21ac844171c61f4ef30cc06b1b8302 Mon Sep 17 00:00:00 2001 From: Jinnapat Indrapiromkul Date: Mon, 6 Oct 2025 11:23:56 +0200 Subject: [PATCH 1/4] Use read_only flag to load qcodes dataset --- plottr/apps/inspectr.py | 5 ++++- plottr/data/qcodes_dataset.py | 16 ++++++++++++---- pyproject.toml | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/plottr/apps/inspectr.py b/plottr/apps/inspectr.py index 4a710ce4..771de0da 100644 --- a/plottr/apps/inspectr.py +++ b/plottr/apps/inspectr.py @@ -579,7 +579,10 @@ def setDateSelection(self, dates: Sequence[str]) -> None: @Slot(int) def setRunSelection(self, runId: int) -> None: assert self.filepath is not None - ds = load_dataset_from(self.filepath, runId) + if sys.version_info >= (3, 11): + ds = load_dataset_from(self.filepath, runId, read_only=True) + else: + ds = load_dataset_from(self.filepath, runId) snap = None if hasattr(ds, 'snapshot'): snap = ds.snapshot diff --git a/plottr/data/qcodes_dataset.py b/plottr/data/qcodes_dataset.py index 28b0c4b3..0e4d0644 100644 --- a/plottr/data/qcodes_dataset.py +++ b/plottr/data/qcodes_dataset.py @@ -4,6 +4,7 @@ Dealing with qcodes dataset (the database) data in plottr. """ import os +import sys from itertools import chain from operator import attrgetter from typing import Dict, List, Set, Union, TYPE_CHECKING, Any, Tuple, Optional, cast @@ -14,7 +15,7 @@ from qcodes.dataset.data_set import load_by_id from qcodes.dataset.experiment_container import experiments -from qcodes.dataset.sqlite.database import initialise_or_create_database_at +from qcodes.dataset.sqlite.database import conn_from_dbpath_or_conn, initialise_or_create_database_at from .datadict import DataDictBase, DataDict, combine_datadicts from ..node.node import Node, updateOption @@ -160,7 +161,7 @@ def get_ds_info(ds: 'DataSetProtocol', get_structure: bool = True) -> DataSetInf return data -def load_dataset_from(path: str, run_id: int) -> 'DataSetProtocol': +def load_dataset_from(path: str, run_id: int, read_only: bool = False) -> 'DataSetProtocol': """ Loads ``DataSet`` with the given ``run_id`` from a database file that is located in in the given ``path``. @@ -169,6 +170,8 @@ def load_dataset_from(path: str, run_id: int) -> 'DataSetProtocol': qcodes config of the current python process is changed to ``path``. """ initialise_or_create_database_at(path) + if sys.version_info >= (3, 11): + return load_by_id(run_id=run_id, read_only=read_only) return load_by_id(run_id=run_id) @@ -187,9 +190,14 @@ def get_runs_from_db(path: str, start: int = 0, in the return dict. """ initialise_or_create_database_at(path) + if sys.version_info >= (3, 11): + conn = conn_from_dbpath_or_conn(read_only=True) + else: + conn = conn_from_dbpath_or_conn() + exps = experiments(conn=conn) datasets = sorted( - chain.from_iterable(exp.data_sets() for exp in experiments()), + chain.from_iterable(exp.data_sets() for exp in exps), key=attrgetter('run_id') ) @@ -286,7 +294,7 @@ def process(self, dataIn: Optional[DataDictBase] = None) -> Optional[Dict[str, A path, runId = cast(Tuple[str, int], self._pathAndId) if self._dataset is None: - self._dataset = load_dataset_from(path, runId) + self._dataset = load_dataset_from(path, runId, read_only=True) if self._dataset.number_of_results > self.nLoadedRecords: diff --git a/pyproject.toml b/pyproject.toml index 615fd005..38be689a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ Tracker = "https://github.com/toolsforexperiments/plottr/issues" pyqt5 = ["PyQt5"] pyqt6 = ["PyQt6"] pyside2 = ["PySide2>=5.12"] -qcodes = ["qcodes"] +qcodes = ["qcodes>=0.54.1"] [project.scripts] plottr-monitr = "plottr.apps.monitr:script" From 8ea8686ed29973f2670980c42bd5d1c67d4434ab Mon Sep 17 00:00:00 2001 From: Jinnapat Indrapiromkul Date: Mon, 6 Oct 2025 12:54:01 +0200 Subject: [PATCH 2/4] set read_only flag for setTag --- plottr/apps/inspectr.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plottr/apps/inspectr.py b/plottr/apps/inspectr.py index 771de0da..f6e9e7f6 100644 --- a/plottr/apps/inspectr.py +++ b/plottr/apps/inspectr.py @@ -610,7 +610,10 @@ def setTag(self, item: QtWidgets.QTreeWidgetItem, tag: str) -> None: # set tag in the database assert self.filepath is not None runId = int(item.text(0)) - ds = load_dataset_from(self.filepath, runId) + if sys.version_info >= (3, 11): + ds = load_dataset_from(self.filepath, runId, read_only=False) + else: + ds = load_dataset_from(self.filepath, runId) ds.add_metadata('inspectr_tag', tag) # set tag in self.dbdf From 9785371715d005c522f1021dc9d4ce29008281f5 Mon Sep 17 00:00:00 2001 From: Mind Date: Mon, 6 Oct 2025 12:55:16 +0200 Subject: [PATCH 3/4] Update plottr/data/qcodes_dataset.py Co-authored-by: Mikhail Astafev --- plottr/data/qcodes_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plottr/data/qcodes_dataset.py b/plottr/data/qcodes_dataset.py index 0e4d0644..c4196083 100644 --- a/plottr/data/qcodes_dataset.py +++ b/plottr/data/qcodes_dataset.py @@ -161,7 +161,7 @@ def get_ds_info(ds: 'DataSetProtocol', get_structure: bool = True) -> DataSetInf return data -def load_dataset_from(path: str, run_id: int, read_only: bool = False) -> 'DataSetProtocol': +def load_dataset_from(path: str, run_id: int, read_only: bool = True) -> 'DataSetProtocol': """ Loads ``DataSet`` with the given ``run_id`` from a database file that is located in in the given ``path``. From 7f69322e7a83f351719d50c3ddc2baecd6fde642 Mon Sep 17 00:00:00 2001 From: Jinnapat Indrapiromkul Date: Tue, 7 Oct 2025 11:19:32 +0200 Subject: [PATCH 4/4] Close sqlite connection after use --- plottr/data/qcodes_dataset.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/plottr/data/qcodes_dataset.py b/plottr/data/qcodes_dataset.py index 0e4d0644..17f94434 100644 --- a/plottr/data/qcodes_dataset.py +++ b/plottr/data/qcodes_dataset.py @@ -5,6 +5,7 @@ """ import os import sys +from contextlib import closing from itertools import chain from operator import attrgetter from typing import Dict, List, Set, Union, TYPE_CHECKING, Any, Tuple, Optional, cast @@ -191,22 +192,23 @@ def get_runs_from_db(path: str, start: int = 0, """ initialise_or_create_database_at(path) if sys.version_info >= (3, 11): - conn = conn_from_dbpath_or_conn(read_only=True) + conn = conn_from_dbpath_or_conn(conn=None, path_to_db=path, read_only=True) else: - conn = conn_from_dbpath_or_conn() - exps = experiments(conn=conn) + conn = conn_from_dbpath_or_conn(conn=None, path_to_db=path) + with closing(conn) as conn_: + exps = experiments(conn=conn_) - datasets = sorted( - chain.from_iterable(exp.data_sets() for exp in exps), - key=attrgetter('run_id') - ) + datasets = sorted( + chain.from_iterable(exp.data_sets() for exp in exps), + key=attrgetter('run_id') + ) - # There is no need for checking whether ``stop`` is ``None`` because if - # it is the following is simply equivalent to ``datasets[start:]`` - datasets = datasets[start:stop] + # There is no need for checking whether ``stop`` is ``None`` because if + # it is the following is simply equivalent to ``datasets[start:]`` + datasets = datasets[start:stop] - overview = {ds.run_id: get_ds_info(ds, get_structure=get_structure) - for ds in datasets} + overview = {ds.run_id: get_ds_info(ds, get_structure=get_structure) + for ds in datasets} return overview