* refactor

* introduce Renderer
simu_flags
agp8x 2017-08-08 14:39:48 +02:00
parent e0398e6494
commit 0711489a81
14 changed files with 219 additions and 153 deletions

View File

@ -1,4 +0,0 @@
from .analyzer import *
from .biogames import *
from .locomotion_action import *
from .mask import *

24
analyzers/__init__.py Normal file
View File

@ -0,0 +1,24 @@
from .analyzer import Analyzer, Result
from .analyzer.biogames import BoardDurationAnalyzer
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.locomotion import LocomotionActionRelativeRender, LocomotionActionAbsoluteRender, \
LocomotionActionRatioRender
__FALLBACK__ = PrintRender
__MAPPING__ = {
LocomotionActionAnalyzer: [
LocomotionActionAbsoluteRender,
LocomotionActionRelativeRender,
LocomotionActionRatioRender],
}
def get_renderer(cls: type) -> [type]:
if cls not in __MAPPING__:
return [__FALLBACK__]
return __MAPPING__[cls]

View File

@ -0,0 +1,30 @@
from analyzers.settings import LogSettings
class Result:
def __init__(self, analysis, result):
self.result = result
self.__analysis__ = analysis
def analysis(self):
return self.__analysis__
def get(self):
return self.result
def __repr__(self):
return "<Result " + str(self.__analysis__) + ": " + str(type(self.result)) + ">"
class Analyzer:
def __init__(self, settings: LogSettings):
self.settings = settings
def process(self, entry: dict) -> bool:
raise NotImplementedError()
def result(self) -> Result:
raise NotImplementedError()
def name(self):
return self.__name__

View File

@ -1,8 +1,4 @@
from collections import defaultdict
from log_analyzer import LogSettings
from .analyzer import Analyzer
from . import Result, LogSettings, Analyzer
class BoardDurationAnalyzer(Analyzer):
@ -12,9 +8,9 @@ class BoardDurationAnalyzer(Analyzer):
__name__ = "BoardDuration"
def render(self) -> str:
return "\n".join(["{}\t{}".format(entry["active"], entry["id"]) for entry in self.result()])
return "\n".join(["{}\t{}".format(entry["active"], entry["id"]) for entry in self.result().get()])
def result(self) -> list:
def result(self) -> Result:
result = []
last_timestamp = None
last_board = None
@ -26,7 +22,7 @@ class BoardDurationAnalyzer(Analyzer):
last_timestamp = timestamp
last_board = board_id
# TODO: last board?
return result
return Result(type(self), result)
def process(self, entry: dict) -> bool:
entry_type = entry[self.settings.type_field]

View File

@ -1,21 +1,7 @@
import json
from collections import defaultdict, Iterable
from collections import defaultdict
from log_analyzer import LogSettings
class Analyzer:
def __init__(self, settings: LogSettings):
self.settings = settings
def process(self, entry: dict) -> bool:
raise NotImplementedError()
def result(self) -> Iterable:
raise NotImplementedError()
def name(self):
return self.__name__
from . import Result, LogSettings, Analyzer
class LocationAnalyzer(Analyzer):
@ -31,8 +17,9 @@ class LocationAnalyzer(Analyzer):
def __init__(self, settings: LogSettings):
super().__init__(settings)
def result(self) -> list:
return self.entries
def result(self) -> Result:
# return self.entries
return Result(type(self), self.entries)
def render(self, format: int = Formats.geojson):
if format is self.Formats.geojson:
@ -51,8 +38,8 @@ class LogEntryCountAnalyzer(Analyzer):
"""
__name__ = "LogEntryCount"
def result(self) -> dict:
return dict(self.store)
def result(self) -> Result:
return Result(type(self), dict(self.store))
def process(self, entry: dict) -> bool:
self.store[entry[self.settings.type_field]] += 1
@ -69,8 +56,8 @@ class LogEntrySequenceAnalyzer(Analyzer):
"""
__name__ = "LogEntrySequence"
def result(self) -> list:
return self.store
def result(self) -> Result:
return Result(type(self), self.store)
def process(self, entry: dict) -> bool:
entry_type = entry[self.settings.type_field]

View File

@ -1,9 +1,5 @@
from collections import defaultdict
from log_analyzer import LogSettings
from .analyzer import Analyzer
from util import combinate
import util
from . import Analyzer, LogSettings, Result
def init_filter(settings: LogSettings, state: str) -> callable:
@ -11,7 +7,7 @@ def init_filter(settings: LogSettings, state: str) -> callable:
if type(settings.sequences[state]) in (str, list):
return lambda entry: entry[settings.type_field] in settings.sequences[state]
else:
return lambda entry: combinate(settings.sequences[state], entry)
return lambda entry: util.combinate(settings.sequences[state], entry)
class LocomotionActionAnalyzer(Analyzer):
@ -45,16 +41,17 @@ class LocomotionActionAnalyzer(Analyzer):
self.current_cache = None
self.last = None
def result(self) -> dict:
def result(self) -> Result:
if self.last is not None:
if self.current_cache is None:
self.locomotion.append(self.last - self.cache_time)
else:
self.actions.append(self.last - self.cache_time)
self.last = None
locomotion = sum(self.locomotion)
action = sum(self.actions)
total = locomotion + action
return {
return Result(type(self), {
'locomotion_sum': locomotion,
'action_sum': action,
'locomotion': self.locomotion,
@ -63,32 +60,7 @@ class LocomotionActionAnalyzer(Analyzer):
'locomotion_relative': locomotion / total,
'action_relative': action / total,
'locomotion_action_ratio': locomotion / action,
}
def render(self):
raw = self.result()
return [
raw['locomotion_sum'],
raw['action_sum'],
raw['locomotion_relative'],
raw['action_relative'],
raw['locomotion_action_ratio']
]
import numpy as np
import matplotlib.pyplot as plt
ind = np.arange(1)
loc = plt.bar(ind, [raw["locomotion_relative"]], 0.35)
act = plt.bar(ind, [raw["action_relative"]], 0.35)
#ratio = plt.plot([1,2,3],[raw['locomotion_action_ratio'],raw['locomotion_relative'],raw['action_relative']], label="ratio", marker=".")
ratio = plt.plot(ind,[raw['locomotion_action_ratio']], label="ratio", marker=".")
plt.ylabel("time")
plt.title("abs locomotion/action")
plt.xlabel("sessions")
plt.xticks(ind, ["s1"])
plt.legend((loc[0], act[0]), ("loc", "act"))
plt.show()
})
def __init__(self, settings: LogSettings):
super().__init__(settings)
@ -114,8 +86,8 @@ class CacheSequenceAnalyzer(Analyzer):
self.store.append((entry['timestamp'], entry['cache']))
return False
def result(self) -> list:
return self.store
def result(self) -> Result:
return Result(type(self), self.store)
def __init__(self, settings: LogSettings):
super().__init__(settings)

View File

@ -1,4 +1,4 @@
from .analyzer import Analyzer
from . import Analyzer
class MaskSpatials(Analyzer):
@ -12,4 +12,4 @@ class MaskSpatials(Analyzer):
return False
def result(self) -> int:
return self.masked
return self.masked

View File

@ -0,0 +1,6 @@
from typing import List
from .. import Result
class Render:
def render(self, results: List[Result]):
raise NotImplementedError()

View File

@ -0,0 +1,8 @@
from typing import List
from . import Render
class PrintRender(Render):
def render(self, results: List):
print("\t" + "\n\t".join([str(r) for r in results]))

View File

@ -0,0 +1,64 @@
from typing import List
import matplotlib.pyplot as plt
import numpy as np
from . import Render
from .. import Result
def plot(results: [[int]], ylabel: str, title: str, legend: (str,) = ("Locomotion", "Action")):
size = len(results)
data = list(zip(*results))
ind = np.arange(size)
width = 0.85
loc = plt.bar(ind, data[0], width=width, color="red")
act = plt.bar(ind, data[1], width=width, bottom=data[0], color="green")
# ratio = plt.plot([1,2,3],[raw['locomotion_action_ratio'],raw['locomotion_relative'],raw['action_relative']], label="ratio", marker=".")
# ratio = plt.plot(ind, data[4], label="ratio", marker=".")
plt.ylabel(ylabel)
plt.title(title)
plt.xlabel("sessions")
# plt.xticks(ind, log_ids)
plt.xticks(ind, [""] * size)
# plt.yticks(np.arange(0,1.1,0.10))
plt.legend((loc[0], act[0]), legend)
plt.show()
def plot_line(results: [[int]], ylabel="Ratio", title="Locomotion/Action "):
size = len(results)
data = list(zip(*results))
ind = np.arange(size)
ratio = plt.plot(ind, data[0], label="ratio", marker=".")
plt.ylabel(ylabel)
plt.title(title)
plt.xticks(ind, [""] * size)
plt.show()
def filter_results(raw_results: [Result], keys) -> [[int]]:
results = []
for result in raw_results:
raw = result.get()
results.append([raw[k] for k in keys])
return results
class LocomotionActionAbsoluteRender(Render):
def render(self, results: List[Result]):
results = filter_results(results, ['locomotion_sum', 'action_sum'])
plot(results, "time", "abs loc/action")
class LocomotionActionRelativeRender(Render):
def render(self, results: List[Result]):
results = filter_results(results, ['locomotion_relative', 'action_relative'])
plot(results, "fraction of time", "rel loc/action")
class LocomotionActionRatioRender(Render):
def render(self, results: List[Result]):
results = filter_results(results, ['locomotion_action_ratio'])
plot_line(results, ylabel="Ratio", title="Locomotion/Action Ratio")

39
analyzers/settings.py Normal file
View File

@ -0,0 +1,39 @@
import json
import sys
class LogSettings:
log_format = None
type_field = None
spatials = None
actions = None
analyzers = []
boards = None
sequences = None
def __init__(self, json_dict):
self.log_format = json_dict['logFormat']
self.type_field = json_dict['entryType']
self.spatials = json_dict['spatials']
self.actions = json_dict['actions']
self.boards = json_dict['boards']
for mod in json_dict['analyzers']:
for name in json_dict['analyzers'][mod]:
print(mod, name)
self.analyzers.append(getattr(sys.modules[mod], name))
self.sequences = json_dict['sequences']
def __repr__(self):
return str({
"logFormat": self.log_format,
"entryType": self.type_field,
"spatials": self.spatials,
"actions": self.actions,
"analyzers": self.analyzers,
"boards": self.boards,
"sequences": self.sequences,
})
def load_settings(file: str) -> LogSettings:
return LogSettings(json.load(open(file)))

View File

@ -12,16 +12,12 @@
"de.findevielfalt.games.game2.instance.log.entry.ShowBoardLogEntry"
],
"analyzers": {
"analyzer": [
"analyzers": [
"LocationAnalyzer",
"LogEntryCountAnalyzer",
"LogEntrySequenceAnalyzer",
"ActionSequenceAnalyzer"
],
"analyzer.biogames": [
"BoardDurationAnalyzer"
],
"analyzer.locomotion_action": [
"ActionSequenceAnalyzer",
"BoardDurationAnalyzer",
"LocomotionActionAnalyzer",
"CacheSequenceAnalyzer"
]

View File

@ -1,47 +1,11 @@
import json
import sys
from load import LOADERS
import analyzer
from typing import List
from analyzers import get_renderer, Analyzer
from analyzers.settings import LogSettings, load_settings
import analyzers
class LogSettings:
log_format = None
type_field = None
spatials = None
actions = None
analyzers = []
boards = None
sequences = None
def __init__(self, json_dict):
self.log_format = json_dict['logFormat']
self.type_field = json_dict['entryType']
self.spatials = json_dict['spatials']
self.actions = json_dict['actions']
self.boards = json_dict['boards']
for mod in json_dict['analyzers']:
for name in json_dict['analyzers'][mod]:
self.analyzers.append(getattr(sys.modules[mod], name))
self.sequences = json_dict['sequences']
def __repr__(self):
return str({
"logFormat": self.log_format,
"entryType": self.type_field,
"spatials": self.spatials,
"actions": self.actions,
"analyzers": self.analyzers,
"boards": self.boards,
"sequences": self.sequences,
})
def load_settings(file: str) -> LogSettings:
return LogSettings(json.load(open(file)))
def process_log(log_id: str, settings: LogSettings) -> List:
def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]:
logfile = "data/inst_{id}/instance_log.sqlite".format(id=log_id)
loader = LOADERS[settings.log_format]()
try:
@ -60,44 +24,27 @@ def process_log(log_id: str, settings: LogSettings) -> List:
if __name__ == '__main__':
settings = load_settings("biogames2.json")
#print(settings)
log_id = "56d9b64144ab44e7b90bf766f3be32e3"
log_ids = ["56d9b64144ab44e7b90bf766f3be32e3","85a9ad58951e4fbda26f860c9b66f567"]
log_ids = ["56d9b64144ab44e7b90bf766f3be32e3", "85a9ad58951e4fbda26f860c9b66f567"]
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.result())
# print(analysis.render())
if analysis.name() in ("LocomotionAction"):
results.append(analysis.render())
results.append(analysis.result())
for r in get_renderer(analyzers.LocomotionActionAnalyzer):
r().render(results)
# for analyzers in analyzers:
# if analyzers.name() in ["LogEntryCount", "ActionSequenceAnalyzer"]:
# print(json.dumps(analyzers.result(), indent=2))
import numpy as np
import matplotlib.pyplot as plt
data = list(zip(*results))
ind = np.arange(len(results))
loc = plt.bar(ind, data[2], width=0.35, color="red")
act = plt.bar(ind, data[3], width=0.35, bottom=data[2], color="green")
# ratio = plt.plot([1,2,3],[raw['locomotion_action_ratio'],raw['locomotion_relative'],raw['action_relative']], label="ratio", marker=".")
#ratio = plt.plot(ind, data[4], label="ratio", marker=".")
plt.ylabel("time")
plt.title("abs locomotion/action")
plt.xlabel("sessions")
# for analyzers in analyzers:
# if analyzers.name() in ["BoardDuration"]:
# print(json.dumps(analyzers.result(), indent=2))
# print(analyzers.render())
#plt.xticks(ind, log_ids)
plt.xticks(ind, [""]*len(results))
#plt.yticks(np.arange(0,1.1,0.10))
plt.legend((loc[0], act[0]), ("loc", "act"))
plt.show()
# for analyzer in analyzers:
# if analyzer.name() in ["LogEntryCount", "ActionSequenceAnalyzer"]:
# print(json.dumps(analyzer.result(), indent=2))
# for analyzer in analyzers:
# if analyzer.name() in ["BoardDuration"]:
# print(json.dumps(analyzer.result(), indent=2))
# print(analyzer.render())
# coords = analyzers[1].render()
# with open("test.js", "w") as out:
# out.write("coords = "+coords)
# coords = analyzers[1].render()
# with open("test.js", "w") as out:
# out.write("coords = "+coords)

View File

@ -1 +1,2 @@
numpy
matplotlib