* 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 . import Result, LogSettings, Analyzer
from log_analyzer import LogSettings
from .analyzer import Analyzer
class BoardDurationAnalyzer(Analyzer): class BoardDurationAnalyzer(Analyzer):
@ -12,9 +8,9 @@ class BoardDurationAnalyzer(Analyzer):
__name__ = "BoardDuration" __name__ = "BoardDuration"
def render(self) -> str: 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 = [] result = []
last_timestamp = None last_timestamp = None
last_board = None last_board = None
@ -26,7 +22,7 @@ class BoardDurationAnalyzer(Analyzer):
last_timestamp = timestamp last_timestamp = timestamp
last_board = board_id last_board = board_id
# TODO: last board? # TODO: last board?
return result return Result(type(self), result)
def process(self, entry: dict) -> bool: def process(self, entry: dict) -> bool:
entry_type = entry[self.settings.type_field] entry_type = entry[self.settings.type_field]

View File

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

View File

@ -1,9 +1,5 @@
from collections import defaultdict import util
from . import Analyzer, LogSettings, Result
from log_analyzer import LogSettings
from .analyzer import Analyzer
from util import combinate
def init_filter(settings: LogSettings, state: str) -> callable: 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): if type(settings.sequences[state]) in (str, list):
return lambda entry: entry[settings.type_field] in settings.sequences[state] return lambda entry: entry[settings.type_field] in settings.sequences[state]
else: else:
return lambda entry: combinate(settings.sequences[state], entry) return lambda entry: util.combinate(settings.sequences[state], entry)
class LocomotionActionAnalyzer(Analyzer): class LocomotionActionAnalyzer(Analyzer):
@ -45,16 +41,17 @@ class LocomotionActionAnalyzer(Analyzer):
self.current_cache = None self.current_cache = None
self.last = None self.last = None
def result(self) -> dict: def result(self) -> Result:
if self.last is not None: if self.last is not None:
if self.current_cache is None: if self.current_cache is None:
self.locomotion.append(self.last - self.cache_time) self.locomotion.append(self.last - self.cache_time)
else: else:
self.actions.append(self.last - self.cache_time) self.actions.append(self.last - self.cache_time)
self.last = None
locomotion = sum(self.locomotion) locomotion = sum(self.locomotion)
action = sum(self.actions) action = sum(self.actions)
total = locomotion + action total = locomotion + action
return { return Result(type(self), {
'locomotion_sum': locomotion, 'locomotion_sum': locomotion,
'action_sum': action, 'action_sum': action,
'locomotion': self.locomotion, 'locomotion': self.locomotion,
@ -63,32 +60,7 @@ class LocomotionActionAnalyzer(Analyzer):
'locomotion_relative': locomotion / total, 'locomotion_relative': locomotion / total,
'action_relative': action / total, 'action_relative': action / total,
'locomotion_action_ratio': locomotion / action, '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): def __init__(self, settings: LogSettings):
super().__init__(settings) super().__init__(settings)
@ -114,8 +86,8 @@ class CacheSequenceAnalyzer(Analyzer):
self.store.append((entry['timestamp'], entry['cache'])) self.store.append((entry['timestamp'], entry['cache']))
return False return False
def result(self) -> list: def result(self) -> Result:
return self.store return Result(type(self), self.store)
def __init__(self, settings: LogSettings): def __init__(self, settings: LogSettings):
super().__init__(settings) super().__init__(settings)

View File

@ -1,4 +1,4 @@
from .analyzer import Analyzer from . import Analyzer
class MaskSpatials(Analyzer): class MaskSpatials(Analyzer):
@ -12,4 +12,4 @@ class MaskSpatials(Analyzer):
return False return False
def result(self) -> int: 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" "de.findevielfalt.games.game2.instance.log.entry.ShowBoardLogEntry"
], ],
"analyzers": { "analyzers": {
"analyzer": [ "analyzers": [
"LocationAnalyzer", "LocationAnalyzer",
"LogEntryCountAnalyzer", "LogEntryCountAnalyzer",
"LogEntrySequenceAnalyzer", "LogEntrySequenceAnalyzer",
"ActionSequenceAnalyzer" "ActionSequenceAnalyzer",
], "BoardDurationAnalyzer",
"analyzer.biogames": [
"BoardDurationAnalyzer"
],
"analyzer.locomotion_action": [
"LocomotionActionAnalyzer", "LocomotionActionAnalyzer",
"CacheSequenceAnalyzer" "CacheSequenceAnalyzer"
] ]

View File

@ -1,47 +1,11 @@
import json
import sys
from load import LOADERS from load import LOADERS
import analyzer
from typing import List from typing import List
from analyzers import get_renderer, Analyzer
from analyzers.settings import LogSettings, load_settings
import analyzers
class LogSettings: def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]:
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:
logfile = "data/inst_{id}/instance_log.sqlite".format(id=log_id) logfile = "data/inst_{id}/instance_log.sqlite".format(id=log_id)
loader = LOADERS[settings.log_format]() loader = LOADERS[settings.log_format]()
try: try:
@ -60,44 +24,27 @@ def process_log(log_id: str, settings: LogSettings) -> List:
if __name__ == '__main__': if __name__ == '__main__':
settings = load_settings("biogames2.json") settings = load_settings("biogames2.json")
#print(settings) log_ids = ["56d9b64144ab44e7b90bf766f3be32e3", "85a9ad58951e4fbda26f860c9b66f567"]
log_id = "56d9b64144ab44e7b90bf766f3be32e3"
log_ids = ["56d9b64144ab44e7b90bf766f3be32e3","85a9ad58951e4fbda26f860c9b66f567"]
results = [] results = []
for log_id in log_ids: for log_id in log_ids:
for analysis in process_log(log_id, settings): for analysis in process_log(log_id, settings):
print("* Result for " + analysis.name()) print("* Result for " + analysis.name())
#print(analysis.result()) # print(analysis.result())
# print(analysis.render())
if analysis.name() in ("LocomotionAction"): 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 # for analyzers in analyzers:
import matplotlib.pyplot as plt # if analyzers.name() in ["BoardDuration"]:
data = list(zip(*results)) # print(json.dumps(analyzers.result(), indent=2))
ind = np.arange(len(results)) # print(analyzers.render())
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")
#plt.xticks(ind, log_ids) # coords = analyzers[1].render()
plt.xticks(ind, [""]*len(results)) # with open("test.js", "w") as out:
#plt.yticks(np.arange(0,1.1,0.10)) # out.write("coords = "+coords)
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)

View File

@ -1 +1,2 @@
numpy
matplotlib matplotlib