From 06a606fbb8182bc5b9e21cbc8e088f964500d7d2 Mon Sep 17 00:00:00 2001 From: agp8x Date: Wed, 9 Aug 2017 15:27:28 +0200 Subject: [PATCH] * add SimulationRoundAnalyzer: count runs of simulation * improve Render-structure --- analyzers/__init__.py | 13 +++++++++---- analyzers/analyzer/biogames.py | 20 ++++++++++++++++++++ analyzers/render/__init__.py | 11 +++++++++++ analyzers/render/default.py | 10 ++++++++-- analyzers/render/locomotion.py | 18 +++++++++++------- analyzers/settings.py | 4 ++++ biogames2.json | 9 +++++++-- load.py | 13 +++++++++++-- log_analyzer.py | 30 ++++++++++++++++++++++++------ 9 files changed, 105 insertions(+), 23 deletions(-) diff --git a/analyzers/__init__.py b/analyzers/__init__.py index 377a221..4d7f5b3 100644 --- a/analyzers/__init__.py +++ b/analyzers/__init__.py @@ -1,10 +1,10 @@ from .analyzer import Analyzer, Result -from .analyzer.biogames import BoardDurationAnalyzer +from .analyzer.biogames import BoardDurationAnalyzer, SimulationRoundsAnalyzer from .analyzer.default import LogEntryCountAnalyzer, LocationAnalyzer, LogEntrySequenceAnalyzer, ActionSequenceAnalyzer from .analyzer.locomotion import LocomotionActionAnalyzer, CacheSequenceAnalyzer from .analyzer.mask import MaskSpatials from .render import Render -from .render.default import PrintRender +from .render.default import PrintRender, JSONRender from .render.locomotion import LocomotionActionRelativeRender, LocomotionActionAbsoluteRender, \ LocomotionActionRatioRender @@ -13,8 +13,13 @@ __MAPPING__ = { LocomotionActionAnalyzer: [ LocomotionActionAbsoluteRender, LocomotionActionRelativeRender, - LocomotionActionRatioRender], - + LocomotionActionRatioRender, ], + LogEntryCountAnalyzer: [ + JSONRender, + ], + SimulationRoundsAnalyzer: [ + JSONRender, + ] } diff --git a/analyzers/analyzer/biogames.py b/analyzers/analyzer/biogames.py index 49ca069..85cfd06 100644 --- a/analyzers/analyzer/biogames.py +++ b/analyzers/analyzer/biogames.py @@ -1,3 +1,5 @@ +from collections import defaultdict + from . import Result, LogSettings, Analyzer @@ -40,3 +42,21 @@ class BoardDurationAnalyzer(Analyzer): super().__init__(settings) self.store = [] self.last = {} + + +class SimulationRoundsAnalyzer(Analyzer): + __name__ = "SimuRounds" + + def __init__(self, settings: LogSettings): + super().__init__(settings) + self.store = defaultdict(lambda: 0) + + def result(self) -> Result: + return Result(type(self), dict(self.store)) + + def process(self, entry: dict) -> bool: + entry_type = entry[self.settings.type_field] + if entry_type in self.settings.custom['simulation_rounds']: + if entry["answers"][self.settings.type_field] in self.settings.custom["simu_data"]: + self.store[entry['answers']["@id"]] += 1 + return False \ No newline at end of file diff --git a/analyzers/render/__init__.py b/analyzers/render/__init__.py index 26c46d8..25b87fc 100644 --- a/analyzers/render/__init__.py +++ b/analyzers/render/__init__.py @@ -1,6 +1,17 @@ from typing import List from .. import Result + class Render: + result_types = [] + def render(self, results: List[Result]): raise NotImplementedError() + + def filter(self, results: List[Result]): + if len(self.result_types) == 0: + return results + return filter(self.__filter__, results) + + def __filter__(self, obj: Result): + return obj.analysis() in self.result_types diff --git a/analyzers/render/default.py b/analyzers/render/default.py index e480132..0aaf858 100644 --- a/analyzers/render/default.py +++ b/analyzers/render/default.py @@ -1,8 +1,14 @@ +import json from typing import List -from . import Render +from . import Render, Result class PrintRender(Render): - def render(self, results: List): + def render(self, results: List[Result]): print("\t" + "\n\t".join([str(r) for r in results])) + + +class JSONRender(Render): + def render(self, results: List[Result]): + print(json.dumps([r.get() for r in self.filter(results)], indent=1)) diff --git a/analyzers/render/locomotion.py b/analyzers/render/locomotion.py index 6d11af2..7ec52f4 100644 --- a/analyzers/render/locomotion.py +++ b/analyzers/render/locomotion.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt import numpy as np from . import Render -from .. import Result +from .. import Result, LocomotionActionAnalyzer def plot(results: [[int]], ylabel: str, title: str, legend: (str,) = ("Locomotion", "Action")): @@ -46,19 +46,23 @@ def filter_results(raw_results: [Result], keys) -> [[int]]: return results -class LocomotionActionAbsoluteRender(Render): +class LocomotionActionRender(Render): + result_types = [LocomotionActionAnalyzer] + + +class LocomotionActionAbsoluteRender(LocomotionActionRender): def render(self, results: List[Result]): - results = filter_results(results, ['locomotion_sum', 'action_sum']) + results = filter_results(self.filter(results), ['locomotion_sum', 'action_sum']) plot(results, "time", "abs loc/action") -class LocomotionActionRelativeRender(Render): +class LocomotionActionRelativeRender(LocomotionActionRender): def render(self, results: List[Result]): - results = filter_results(results, ['locomotion_relative', 'action_relative']) + results = filter_results(self.filter(results), ['locomotion_relative', 'action_relative']) plot(results, "fraction of time", "rel loc/action") -class LocomotionActionRatioRender(Render): +class LocomotionActionRatioRender(LocomotionActionRender): def render(self, results: List[Result]): - results = filter_results(results, ['locomotion_action_ratio']) + results = filter_results(self.filter(results), ['locomotion_action_ratio']) plot_line(results, ylabel="Ratio", title="Locomotion/Action Ratio") diff --git a/analyzers/settings.py b/analyzers/settings.py index 88cb135..029d112 100644 --- a/analyzers/settings.py +++ b/analyzers/settings.py @@ -10,6 +10,7 @@ class LogSettings: analyzers = [] boards = None sequences = None + custom = None def __init__(self, json_dict): self.log_format = json_dict['logFormat'] @@ -22,6 +23,8 @@ class LogSettings: print(mod, name) self.analyzers.append(getattr(sys.modules[mod], name)) self.sequences = json_dict['sequences'] + if 'custom' in json_dict: + self.custom = json_dict['custom'] def __repr__(self): return str({ @@ -32,6 +35,7 @@ class LogSettings: "analyzers": self.analyzers, "boards": self.boards, "sequences": self.sequences, + "custom": self.custom, }) diff --git a/biogames2.json b/biogames2.json index aad69dc..7e124e1 100644 --- a/biogames2.json +++ b/biogames2.json @@ -1,5 +1,5 @@ { - "logFormat": "sqlite", + "logFormat": "zip", "entryType": "@class", "spatials": [ "de.findevielfalt.games.game2.instance.log.entry.LogEntryLocation" @@ -19,7 +19,8 @@ "ActionSequenceAnalyzer", "BoardDurationAnalyzer", "LocomotionActionAnalyzer", - "CacheSequenceAnalyzer" + "CacheSequenceAnalyzer", + "SimulationRoundsAnalyzer" ] }, "sequences": { @@ -28,5 +29,9 @@ "@class": "de.findevielfalt.games.game2.instance.log.entry.LogEntryInstanceAction", "action.@class": "de.findevielfalt.games.game2.instance.action.CacheEnableAction" } + }, + "custom":{ + "simulation_rounds": ["de.findevielfalt.games.game2.instance.log.entry.LogEntryQuestion"], + "simu_data": ["de.findevielfalt.games.game2.instance.data.sequence.simulation.SimulationBoardData"] } } \ No newline at end of file diff --git a/load.py b/load.py index b9610bd..36b8f94 100644 --- a/load.py +++ b/load.py @@ -1,6 +1,7 @@ import json import sqlite3 - +import tempfile +import zipfile from json import loads as json_loads @@ -36,7 +37,15 @@ class SQLiteLoader(Loader): yield json_loads(json) +class ZipSQLiteLoader(SQLiteLoader): + def load(self, file: str): + with zipfile.ZipFile(file, "r") as zipped_log, tempfile.TemporaryDirectory() as tmp: + zipped_log.extract("instance_log.sqlite", path=tmp) + super(ZipSQLiteLoader, self).load("{dir}/instance_log.sqlite".format(dir=tmp)) + + LOADERS = { "json": JSONLoader, - "sqlite": SQLiteLoader + "sqlite": SQLiteLoader, + "zip": ZipSQLiteLoader } diff --git a/log_analyzer.py b/log_analyzer.py index f0c6ef6..a4e3abd 100644 --- a/log_analyzer.py +++ b/log_analyzer.py @@ -6,7 +6,7 @@ import analyzers def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]: - logfile = "data/inst_{id}/instance_log.sqlite".format(id=log_id) + logfile = "data/inst_{id}.{format}".format(id=log_id, format=settings.log_format) loader = LOADERS[settings.log_format]() try: loader.load(logfile) @@ -24,17 +24,35 @@ def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]: if __name__ == '__main__': settings = load_settings("biogames2.json") - log_ids = ["56d9b64144ab44e7b90bf766f3be32e3", "85a9ad58951e4fbda26f860c9b66f567"] + log_ids = [ + "20d4244719404ffab0ca386c76e4b112", + "56d9b64144ab44e7b90bf766f3be32e3", + "dc2cdc28ca074715b905e4aa5badff10", + "e32b16998440475b994ab46d481d3e0c", ] + log_ids = [ + "34fecf49dbaca3401d745fb467", + "44ea194de594cd8d63ac0314be", + "57c444470dbf88605433ca935c", + "78e0c545b594e82edfad55bd7f", + "91abfd4b31a5562b1c66be37d9", + "597b704fe9ace475316c345903", + "e01a684aa29dff9ddd9705edf8", + "fbf9d64ae0bdad0de7efa3eec6", + "fe1331481f85560681f86827ec", + "fec57041458e6cef98652df625", ] results = [] for log_id in log_ids: for analysis in process_log(log_id, settings): print("* Result for " + analysis.name()) # print(analysis.result()) # print(analysis.render()) - if analysis.name() in ("LocomotionAction"): - results.append(analysis.result()) - for r in get_renderer(analyzers.LocomotionActionAnalyzer): - r().render(results) + results.append(analysis.result()) + if False: + for r in get_renderer(analyzers.LocomotionActionAnalyzer): + r().render(results) + jr = analyzers.JSONRender() + jr.result_types = [analyzers.SimulationRoundsAnalyzer] + jr.render(results) # for analyzers in analyzers: # if analyzers.name() in ["LogEntryCount", "ActionSequenceAnalyzer"]: