Source code for qumada.utils.load_from_sqlite_db

# Copyright (c) 2023 JARA Institute for Quantum Information
#
# This file is part of QuMADA.
#
# QuMADA is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# QuMADA is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# QuMADA. If not, see <https://www.gnu.org/licenses/>.
#
# Contributors:
# - Daniel Grothe
# - Sionludi Lab
# - Till Huckeman


"""
Loading data from Database
"""
from __future__ import annotations

from os import path

import numpy as np
import qcodes as qc
from qcodes.dataset.data_set import DataSet
from qcodes.dataset.plotting import plot_dataset

from qumada.utils.browsefiles import browsefiles


# %%
[docs]def flatten_list(lst: list) -> list: """ Flattens nested lists """ results = [] def rec(sublist, results): for entry in sublist: if isinstance(entry, list): rec(entry, results) else: results.append(entry) rec(lst, results) return results
# %%
[docs]def load_db(filepath: str | None = None) -> None: """ Loads or creates the database. Parameters ---------- filepath : str, optional Provide the path to the DB here if you want to skip the file explorer. The default is None. Returns ------- None. #TODO: Checks only whether provided path is a file but not which type. """ if not filepath: filetypes = (("DB Files", "*.db*"), ("All files", "*.*")) filepath = browsefiles(filetypes=filetypes) if filepath == "": return None try: qc.initialise_or_create_database_at(filepath) return None except Exception: print("Please provide a valid path") return load_db(None) elif not path.isfile(filepath): try: qc.initialise_or_create_database_at(filepath) print("Created new Database") return None except Exception as e: print("Please provide a valid path") raise e else: try: qc.initialise_or_create_database_at(filepath) except Exception: print("The file you want to load is no valid db file!") return load_db(None)
# %%
[docs]def list_sample_names() -> set[str]: """ Lists all sample names that appear in the database """ name_set = {measurement.sample_name for measurement in qc.experiments()} return name_set
# %% def _pick_sample_name() -> str: """ Lists all samples and allows the user to pick one. Returns String with sample name """ samples = list(list_sample_names()) print("Please choose a sample:") for idx, sample in enumerate(samples): print(f"{idx}: {sample}") while True: try: chosen = samples[int(input("Enter sample number: "))] return chosen except Exception: print("Please chose a valid entry") # %%
[docs]def list_measurements_for_sample(sample_name: str | None = None) -> list[qc.DataSet]: """ Lists all measurements done with a certain sample in the console. If no sample is provided it helps you to find one. Returns list with all datasets belonging to the sample specified. Parameters ---------- sample_name : str, optional In case you do not want to do this via user input. The default is None. Returns ------- list """ if not sample_name: sample_name = _pick_sample_name() try: qc.load_by_run_spec(sample_name=sample_name) except NameError: pass return _list_measurements_for_sample(sample_name)
# %% def _list_measurements_for_sample(sample_name: str | None = None) -> list[qc.DataSet]: """ Returns flattened list containing all datasets belonging to the sample specified """ datasets = [] for experiment in qc.experiments(): if experiment.sample_name == sample_name: datasets.append([*(dataset for dataset in experiment.data_sets())]) return flatten_list(datasets) # %% def _flatten_experiment_container() -> list[qc.DataSet]: """ Returns flattened list of all datasets in the currently loaded .db """ datasets = [*(experiment.data_sets() for experiment in qc.experiments())] return flatten_list(datasets) # %%
[docs]def pick_measurement(sample_name: str = None, preview_dialogue=True): """ Returns a measurement of your choice, plots it if you want. Interactive, if no sample_name is provided. """ measurements = list_measurements_for_sample(sample_name=sample_name) for idx, measurement in enumerate(measurements): print(f"{idx} (Run ID {measurement.run_id}) : {measurement.name}") chosen = int(input("Please choose a measurement: ")) chosen_measurement = measurements[int(chosen)] if preview_dialogue: preview = str(input("Do you want to see a plot? (Y/N) ")) if str.lower(preview) == "y": plot_dataset(chosen_measurement) return chosen_measurement
# %%
[docs]def pick_measurements(sample_name: str = None, preview_dialogue=False, measurement_list=None): """ Returns a measurement of your choice, plots it if you want. Interactive, if no sample_name is provided. """ if not measurement_list: measurement_list = list() measurements = list_measurements_for_sample(sample_name=sample_name) for idx, measurement in enumerate(measurements): print(f"{idx} (Run ID {measurement.run_id}) : {measurement.name}") while True: chosen = input("Please choose a measurement: ") if chosen == "f": return measurement_list if chosen == "s": return pick_measurements(preview_dialogue=preview_dialogue, measurement_list=measurement_list) chosen = int(chosen) measurement_list.append(measurements[int(chosen)]) print("Please enter 'f' when your are finished or 's' if you want to add measurements of another sample")
# %%
[docs]def plot_data(sample_name: str = None): """ Simple plotting of datasets from the QCoDeS DB. """ dataset = pick_measurement(sample_name=sample_name, preview_dialogue=False) independend_parameters = list() dependend_parameters = list() for parameter in dataset.get_parameters(): if len(parameter._depends_on) == 0: independend_parameters.append(parameter) else: dependend_parameters.append(parameter) print("Which parameter do you want to plot?") for idx, parameter in enumerate(dependend_parameters): print(f"{idx} : {parameter.label}") plot_param_numbers = input("Please enter the numbers of the parameters you want to plot, separated by blank") plot_params = list() for param in plot_param_numbers: plot_params.append(dependend_parameters[int(param)].name) print(plot_params) for param in plot_params: y_data = dataset.get_parameter_data(param)[param][param] print(dataset.get_parameter_data(param)[param]) x_data = dataset.get_parameter_data(param)[param][dependend_parameters[0].name] print(y_data) print(x_data)
# %%
[docs]def get_parameter_data(dataset=None, parameter_name=None, **kwargs): """ Gets you the data for a chosen dependent parameter and the data of the first (!) parameter it depends on #TODO: Support for independent parameters """ if not dataset: dataset = pick_measurement() if not isinstance(dataset, DataSet): print("Dataset has to be of type DataSet") return None if not parameter_name: for idx, parameter in enumerate(dataset.dependent_parameters): print(f"{idx} : {parameter.label} / {parameter.name}") chosen_param_num = int(input("Please enter number: ")) chosen_param = dataset.dependent_parameters[chosen_param_num] parameter_name = chosen_param.name else: chosen_param = dataset.paramspecs[parameter_name] independent_param = dataset.paramspecs[parameter_name]._depends_on # if not isinstance(independent_param, str): # independent_param = independent_param[0] params = (*independent_param, parameter_name) labels = (*(dataset.paramspecs[i_p].label for i_p in independent_param), chosen_param.label) units = (*(dataset.paramspecs[i_p].unit for i_p in independent_param), chosen_param.unit) data = ( *tuple(dataset.get_parameter_data(parameter_name)[parameter_name][param] for param in independent_param), dataset.get_parameter_data(parameter_name)[parameter_name][parameter_name], ) return zip(params, data, units, labels)
# %%
[docs]def separate_up_down(x_data, y_data): grad = np.gradient(x_data) curr_sign = np.sign(grad[0]) data_list_x = list() data_list_y = list() direction = list() direction.append(curr_sign) start_helper = 0 for i in range(0, len(grad)): if np.sign(grad[i]) != curr_sign: data_list_x.append(x_data[start_helper:i]) data_list_y.append(y_data[start_helper:i]) start_helper = i + 1 curr_sign = np.sign(grad[i]) direction.append(curr_sign) data_list_x.append(x_data[start_helper : len(grad)]) data_list_y.append(y_data[start_helper : len(grad)]) if len(direction) == 0: direction.append(1) return data_list_x, data_list_y, direction