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()
Example #2
0
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()
Example #3
0
 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()
Example #4
0
 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()
Example #5
0
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()
Example #6
0
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