def __init__(self, path_to_db: Optional[str] = None, exp_id: Optional[int] = None, name: Optional[str] = None, sample_name: Optional[str] = None, format_string: str = "{}-{}-{}", conn: Optional[ConnectionPlus] = None) -> None: """ Create or load an experiment. If exp_id is None, a new experiment is created. If exp_id is not None, an experiment is loaded. Args: path_to_db: The path of the database file to create in/load from. If a conn is passed together with path_to_db, an exception is raised exp_id: The id of the experiment to load name: The name of the experiment to create. Ignored if exp_id is not None sample_name: The sample name for this experiment. Ignored if exp_id is not None format_string: The format string used to name result-tables. Ignored if exp_id is not None. conn: connection to the database. If not supplied, the constructor first tries to use path_to_db to figure out where to connect to. If path_to_db is not supplied either, a new connection to the DB file specified in the config is made """ if path_to_db is not None and conn is not None: raise ValueError('Received BOTH conn and path_to_db. Please ' 'provide only one or the other.') self._path_to_db = path_to_db or get_DB_location() self.conn = conn or connect(self.path_to_db, get_DB_debug()) max_id = len(get_experiments(self.conn)) if exp_id is not None: if exp_id not in range(1, max_id + 1): raise ValueError('No such experiment in the database') self._exp_id = exp_id else: # it is better to catch an invalid format string earlier than later try: # the corresponding function from sqlite module will try to # format as `(name, exp_id, run_counter)`, hence we prepare # for that here format_string.format("name", 1, 1) except Exception as e: raise ValueError("Invalid format string. Can not format " "(name, exp_id, run_counter)") from e log.info("creating new experiment in {}".format(self.path_to_db)) name = name or f"experiment_{max_id+1}" sample_name = sample_name or "some_sample" self._exp_id = ne(self.conn, name, sample_name, format_string)
def _create_exp_if_needed( target_conn: ConnectionPlus, exp_name: str, sample_name: str, fmt_str: str, start_time: float, end_time: Union[float, None], ) -> int: """ Look up in the database whether an experiment already exists and create it if it doesn't. Note that experiments do not have GUIDs, so this method is not guaranteed to work. Matching names and times is the best we can do. """ matching_exp_ids = get_matching_exp_ids( target_conn, name=exp_name, sample_name=sample_name, format_string=fmt_str, start_time=start_time, end_time=end_time, ) if len(matching_exp_ids) > 1: exp_id = matching_exp_ids[0] warn(f"{len(matching_exp_ids)} experiments found in target DB that " "match name, sample_name, fmt_str, start_time, and end_time. " f"Inserting into the experiment with exp_id={exp_id}.") return exp_id if len(matching_exp_ids) == 1: return matching_exp_ids[0] else: lastrowid = ne( target_conn, name=exp_name, sample_name=sample_name, format_string=fmt_str, start_time=start_time, end_time=end_time, ) return lastrowid