def __init__(self, h5file: tables.File, parent_group: tables.Group, exp_id: str, exp_title: str, variables: Mapping[str, VarType]): super(_ExperimentWriter, self).__init__() self._id = exp_id self._title = exp_title self._file = h5file try: self._group = h5file.create_group(parent_group, exp_id, title=exp_title) except tables.NodeError: try: node = h5file.get_node(parent_group, exp_id) path = node._v_pathname if isinstance(node, tables.Group): raise ExperimentElementError('Experiment already exists at' f'{path} in file {h5file}.') elif isinstance(node, tables.Table): raise ExperimentElementError('Name conflict: variable ' 'table already exists at ' f'{path} in file {h5file}') else: raise ExperimentElementError(f'Conflict at {path} ' f'in file {h5file}') except tables.NoSuchNodeError as e: raise ExperimentElementError() from e # metadata self._group._v_attrs.created = datetime.datetime.now().isoformat() self._group._v_attrs.finished = 'unfinished' self._var_tables = dict() for var_name, var_type in variables.items(): try: tbl = h5file.create_table(self._group, var_name, description={ 'record_time': tables.Time64Col(), 'experiment_time': tables.Time64Col(), 'value': _vartype_columns[var_type]() }) self._var_tables[var_name] = tbl except KeyError: raise UnsupportedVariableType(var_type) self._sub_experiments = dict()
def _add_agent(results_file: tables.File, agent_name: str) -> None: """ Implementation for `add_agent`. See that function for a description of this code. See Also -------- add_agent : The externally callable wrapper for this function """ avt: tables.Table try: avt = results_file.get_node("/agents", agent_name) except tables.NoSuchNodeError: avt = results_file.create_table("/agents", agent_name, AgentVersionRow, createparents=True) n_versions = avt.nrows t_uploaded = time.time() t_str = time.ctime() av_row = avt.row av_row["version"] = n_versions av_row["uploaded/time_str"] = t_str av_row["uploaded/time_sec"] = t_uploaded av_row.append() avt.flush() found = False for ac_row in results_file.root.current.where( f'(name == b"{agent_name}")'): assert ( not found ), f"There was more than one row with the same agent name: {agent_name}" found = True ac_row["version"] = n_versions ac_row["uploaded/time_str"] = t_str ac_row["uploaded/time_sec"] = t_uploaded ac_row.update() if not found: ac_row = results_file.root.current.row ac_row["name"] = agent_name ac_row["version"] = n_versions ac_row["uploaded/time_str"] = t_str ac_row["uploaded/time_sec"] = t_uploaded ac_row.append() results_file.root.current.flush()
def __call__(self, path: str, h5file: File, group: Group): data = np.loadtxt(path, **self.kwargs) if data.size == 1: data = data.reshape((1, )) self.tableName = self.filename[:self.filename.rfind('.')] try: my_table = h5file.create_table(group, self.tableName, obj=data, **self.settings) except IndexError: print(group, self.tableName, data, data.size, type(data), data.shape) raise my_table.flush()
def __call__(self, path: str, h5file: File, group: Group): data = np.fromfile(path, dtype=self.dtype) self.tableName = self.filename[:self.filename.rfind('.')] if ("e-" in self.tableName): self.tableName = self.tableName.replace("e-", "electron") if ("e+" in self.tableName): self.tableName = self.tableName.replace("e+", "positron") # if data.size == 0: # my_table = h5file.create_table(group, self.tableName, desc **self.settings) # else: my_table = h5file.create_table(group, self.tableName, obj=data, **self.settings) my_table.flush()
def _record_outcome( results_file: tables.File, game_result: GameResult, agent_1_version: int, agent_2_version: int, agent_1_game_number: int, agent_2_game_number: int, ) -> None: """ Record the outcome of a single game for both agents that participated in it. More specifically, this function increments the number of wins / losses / draws / failures for the two agents, and then records a summary of the game in the `all_games` table. Parameters ---------- results_file : tables.File game_result : GameResult agent_1_version : int agent_2_version : int agent_1_game_number : int agent_2_game_number : int """ for result in (game_result.result_1, game_result.result_2): agent_name = result.name outcome = result.outcome vt: tables.Table = results_file.get_node("/agents", agent_name) first = True for row in vt.iterrows(start=-1): assert ( first ), "We only want to update the last row, so this loop should only be entered once." first = False if outcome == "WIN": row["won"] += 1 elif outcome == "LOSS": row["lost"] += 1 elif outcome == "DRAW": row["drawn"] += 1 else: row["failed"] += 1 row.update() vt.flush() agent_version = [agent_1_version, agent_2_version] game_numbers = [agent_1_game_number, agent_2_game_number] result_1, result_2 = game_result.result_1, game_result.result_2 agt: tables.Table try: agt = results_file.root.all_games except tables.NoSuchNodeError: agt = results_file.create_table("/", "all_games", GameSummaryRow) gr = agt.row gr["winner"] = game_result.winner gr["moves"] = len(result_1.moves) + len(result_2.moves) gr["when/time_str"] = game_result.time_str gr["when/time_sec"] = game_result.time_sec for i, result in enumerate((result_1, result_2), 1): gr[f"agent{i}/name"] = result.name gr[f"agent{i}/version"] = agent_version[i - 1] gr[f"agent{i}/game_number"] = game_numbers[i - 1] gr[f"agent{i}/rating"] = 0.0 gr[f"agent{i}/outcome"] = result.outcome if result.move_times: gr[f"agent{i}/total_time"] = np.sum(result.move_times) gr[f"agent{i}/time_med"] = np.median(result.move_times) gr[f"agent{i}/time_max"] = np.max(result.move_times) else: gr[f"agent{i}/total_time"] = -1 gr[f"agent{i}/time_med"] = -1 gr[f"agent{i}/time_max"] = -1 if result.state_size: gr[f"agent{i}/state_size_med"] = np.median(result.state_size) gr[f"agent{i}/state_size_max"] = np.max(result.state_size) else: gr[f"agent{i}/state_size_med"] = -1 gr[f"agent{i}/state_size_max"] = -1 gr.append() agt.flush()
def _add_game_for_agent( agent_file: tables.File, agent_name: str, agent_version: int, opponent_version: int, game_result: GameResult, ) -> int: """ Create a complete record of a game played by an agent. Parameters ---------- agent_file : tables.File agent_name : str agent_version : int opponent_version : int game_result : GameResult Returns ------- game_number : int """ ver_str = _version_string(agent_version) gt: tables.Table vg: tables.Group try: vg = agent_file.get_node("/", ver_str) except tables.NoSuchNodeError: vg = agent_file.create_group("/", ver_str) try: gt = agent_file.get_node(vg, "games") except tables.NoSuchNodeError: gt = agent_file.create_table(vg, "games", AgentGameOutcomeRow) result_1 = game_result.result_1 result_2 = game_result.result_2 game_number = gt.nrows moved_first = agent_name == result_1.name if moved_first: result_agent = result_1 result_opponent = result_2 else: result_agent = result_2 result_opponent = result_1 opponent_name = result_opponent.name gt_row = gt.row gt_row["game_number"] = game_number gt_row["opponent"] = opponent_name gt_row["version"] = opponent_version gt_row["moved_first"] = moved_first gt_row["outcome"] = result_agent.outcome gt_row["when/time_str"] = game_result.time_str gt_row["when/time_sec"] = game_result.time_sec gt_row.append() game_number_str = _game_string(game_number) gg = agent_file.create_group(vg, game_number_str) for n in ("moves", "move_times"): _add_array(agent_file, gg, n, getattr(result_1, n), getattr(result_2, n)) _add_array(agent_file, gg, "state_size", result_agent.state_size) _add_array(agent_file, gg, "seeds", result_agent.seeds) for n in ("stdout", "stderr"): _add_vlarray(agent_file, gg, n, getattr(result_agent, n)) agent_file.flush() return game_number