diff --git a/analyzers/__init__.py b/analyzers/__init__.py index 1a098ff..8bb53dd 100644 --- a/analyzers/__init__.py +++ b/analyzers/__init__.py @@ -9,23 +9,25 @@ from .analyzer.locomotion import LocomotionActionAnalyzer, CacheSequenceAnalyzer from .analyzer.mask import MaskSpatials from .render import Render from .render.biogames import SimulationRoundsRender, BoardDurationHistRender, BoardDurationBoxRender, \ - ActivityMapperRender, StoreRender + ActivityMapperRender, StoreRender, SimulationRoundsMeanRender from .render.default import PrintRender, JSONRender, TrackRender, HeatMapRender from .render.locomotion import LocomotionActionRelativeRender, LocomotionActionAbsoluteRender, \ - LocomotionActionRatioRender + LocomotionActionRatioRender, LocomotionActionRatioHistRender __FALLBACK__ = PrintRender __MAPPING__ = { LocomotionActionAnalyzer: [ LocomotionActionAbsoluteRender, LocomotionActionRelativeRender, - LocomotionActionRatioRender, ], + LocomotionActionRatioRender, + LocomotionActionRatioHistRender, + ], LogEntryCountAnalyzer: [ JSONRender, ], SimulationRoundsAnalyzer: [ - JSONRender, SimulationRoundsRender, + SimulationRoundsMeanRender, ], BoardDurationAnalyzer: [ BoardDurationHistRender, diff --git a/analyzers/analyzer/__init__.py b/analyzers/analyzer/__init__.py index bdfe6db..5ccea84 100644 --- a/analyzers/analyzer/__init__.py +++ b/analyzers/analyzer/__init__.py @@ -17,7 +17,6 @@ class Result: return self.__analysis__ def get(self): - log.debug("get" + str(len(self.result))) return self.result def __repr__(self): diff --git a/analyzers/analyzer/biogames.py b/analyzers/analyzer/biogames.py index 57fb2cb..263bd62 100644 --- a/analyzers/analyzer/biogames.py +++ b/analyzers/analyzer/biogames.py @@ -28,7 +28,7 @@ class BoardDurationAnalyzer(Analyzer): board_id, timestamp = board["id"], board["timestamp"] if not last_timestamp is None: - result.append(self.save_entry(last_board, last_timestamp, timestamp - last_timestamp)) + result.append(self.save_entry(last_board, last_timestamp, (timestamp - last_timestamp)/1000)) last_timestamp = timestamp last_board = board_id # TODO: last board? @@ -126,7 +126,12 @@ class ActivityMapper(Analyzer): sequence_id=active_segment.sequence, ) source = self.settings.source - seq_data = source._get(seq_data_url).json() + seq_data = source._get(seq_data_url) + if not seq_data.ok: + logger.error("HTTP ERROR:", seq_data) + seq_data = {} + else: + seq_data = seq_data.json() # TODO: use sequence names logger.warning(seq_data) for event in active_segment.events: diff --git a/analyzers/analyzer/locomotion.py b/analyzers/analyzer/locomotion.py index 671680a..55705f1 100644 --- a/analyzers/analyzer/locomotion.py +++ b/analyzers/analyzer/locomotion.py @@ -1,6 +1,10 @@ +import logging import util from . import Analyzer, LogSettings, Result, ResultStore +log: logging.Logger = logging.getLogger(__name__) +ONE_DAY = 24 * 60 * 60 * 1000 +MIN_DURATION = 5 * 60 * 1000 def init_filter(settings: LogSettings, state: str) -> callable: # this implies OR for lists; AND for dicts @@ -19,6 +23,8 @@ class LocomotionActionAnalyzer(Analyzer): """ __name__ = "LocomotionAction" + limit = ONE_DAY + def process(self, entry: dict) -> bool: self.last_timestamp = entry["timestamp"] if self.instance_start is None: @@ -50,17 +56,26 @@ class LocomotionActionAnalyzer(Analyzer): self.last = None locomotion = sum(self.locomotion) action = sum(self.actions) + if not action > 0: + action = 1 total = locomotion + action - store.add(Result(type(self), { - 'locomotion_sum': locomotion, - 'action_sum': action, - 'locomotion': self.locomotion, - 'action': self.actions, - 'duration': (self.last_timestamp - self.instance_start), - 'locomotion_relative': locomotion / total, - 'action_relative': action / total, - 'locomotion_action_ratio': locomotion / action, - })) + if total > self.limit: + log.error("total duration over limit, skip") + elif total < MIN_DURATION: + log.error("total duration too short, skip") + elif action < MIN_DURATION: + log.error("action time too short, skip") + else: + store.add(Result(type(self), { + 'locomotion_sum': locomotion/1000, + 'action_sum': action/1000, + 'locomotion': self.locomotion, + 'action': self.actions, + 'duration': (self.last_timestamp - self.instance_start)/1000, + 'locomotion_relative': locomotion / total, + 'action_relative': action / total, + 'locomotion_action_ratio': locomotion / action, + })) def __init__(self, settings: LogSettings): super().__init__(settings) diff --git a/analyzers/render/biogames.py b/analyzers/render/biogames.py index 7aea6ab..48d27bd 100644 --- a/analyzers/render/biogames.py +++ b/analyzers/render/biogames.py @@ -10,17 +10,21 @@ from . import Render from .. import Result, SimulationRoundsAnalyzer, BoardDurationAnalyzer, ActivityMapper -def plot(src_data: List[Tuple[str, List[int]]]): +ONE_DAY = 24 * 60 * 60 + +def plot(src_data: List[Tuple[str, List[int]]], title:str="simulation retries", ylabel:str="simulation rounds", xargs={}): names, datas = list(zip(*src_data)) - plt.boxplot(datas, labels=names) + plt.boxplot(datas, labels=names, **xargs) plt.xticks(rotation='vertical') # plt.margins() - plt.ylabel("simulation rounds") - plt.title("simulation retries") + plt.ylabel(ylabel) + plt.title(title) plt.show() class SimulationRoundsRender(Render): + result_types = [SimulationRoundsAnalyzer] + xargs = {} def render(self, results: List[Result]): data = defaultdict(list) for result in self.filter(results): @@ -29,22 +33,32 @@ class SimulationRoundsRender(Render): data[key].append(get[key]) data_tuples = [(key, data[key]) for key in sorted(data)] data_tuples = sorted(data_tuples, key=lambda x: sum(x[1])) - plot(data_tuples) + plot(data_tuples, xargs=self.xargs) result_types = [SimulationRoundsAnalyzer] +class SimulationRoundsMeanRender(SimulationRoundsRender): + xargs = {"showfliers": False} + class BoardDurationHistRender(Render): result_types = [BoardDurationAnalyzer] def render(self, results: List[Result]): + plt.title("board display duration") + plt.xlabel("display time") + plt.ylabel("# of boards") data = [] for result in self.filter(results): session = result.get() _data = [] for board in session: if "active" in board: - _data.append(board["active"]) + value = board["active"] + if value > ONE_DAY: + _data.append(0) + else: + _data.append(value) else: _data.append(0) data.append(_data) @@ -61,10 +75,11 @@ class BoardDurationBoxRender(Render): get = result.get() for board in get: duration = board['active'] if 'active' in board else 0 - data[board['id']].append(duration) + if duration < ONE_DAY: + data[board['id']].append(duration) data_tuples = [(key, data[key]) for key in sorted(data)] data_tuples = sorted(data_tuples, key=lambda x: sum(x[1])) - plot(data_tuples) + plot(data_tuples, "board duration", "display time", xargs={"showfliers": False}) class ActivityMapperRender(Render): diff --git a/analyzers/render/locomotion.py b/analyzers/render/locomotion.py index 7ec52f4..96a71c1 100644 --- a/analyzers/render/locomotion.py +++ b/analyzers/render/locomotion.py @@ -1,3 +1,5 @@ +import json +import logging from typing import List import matplotlib.pyplot as plt @@ -6,6 +8,14 @@ import numpy as np from . import Render from .. import Result, LocomotionActionAnalyzer +log = logging.getLogger(__name__) + +def default(item): + return item +def sort(item): + return item[0] +def sort_sum(item): + return sum(item) def plot(results: [[int]], ylabel: str, title: str, legend: (str,) = ("Locomotion", "Action")): size = len(results) @@ -38,11 +48,12 @@ def plot_line(results: [[int]], ylabel="Ratio", title="Locomotion/Action "): plt.show() -def filter_results(raw_results: [Result], keys) -> [[int]]: +def filter_results(raw_results: [Result], keys, sort=default) -> [[int]]: results = [] for result in raw_results: raw = result.get() results.append([raw[k] for k in keys]) + results = sorted(results,key=sort) return results @@ -52,13 +63,14 @@ class LocomotionActionRender(Render): class LocomotionActionAbsoluteRender(LocomotionActionRender): def render(self, results: List[Result]): - results = filter_results(self.filter(results), ['locomotion_sum', 'action_sum']) + results = filter_results(self.filter(results), ['locomotion_sum', 'action_sum'], sort) plot(results, "time", "abs loc/action") class LocomotionActionRelativeRender(LocomotionActionRender): def render(self, results: List[Result]): - results = filter_results(self.filter(results), ['locomotion_relative', 'action_relative']) + results = filter_results(self.filter(results), ['locomotion_relative', 'action_relative'], sort) + log.error(json.dumps(results[-10:], indent=2)) plot(results, "fraction of time", "rel loc/action") @@ -66,3 +78,12 @@ class LocomotionActionRatioRender(LocomotionActionRender): def render(self, results: List[Result]): results = filter_results(self.filter(results), ['locomotion_action_ratio']) plot_line(results, ylabel="Ratio", title="Locomotion/Action Ratio") + +class LocomotionActionRatioHistRender(LocomotionActionRender): + def render(self, results: List[Result]): + results = filter_results(self.filter(results), ['locomotion_action_ratio']) + plt.title("locomotion/action") + plt.xlabel("ratio") + plt.ylabel("frequency") + n, bins, patches = plt.hist([results], bins=len(results)) + plt.show() \ No newline at end of file diff --git a/biogames2.json b/biogames2.json index 1bebe72..3ee97c7 100644 --- a/biogames2.json +++ b/biogames2.json @@ -14,11 +14,17 @@ "analyzers": { "analyzers": [ "BiogamesCategorizer", - "ActivityMapper", + "ActionSequenceAnalyzer", + "BoardDurationAnalyzer", + "LocomotionActionAnalyzer", + "CacheSequenceAnalyzer", + "SimulationRoundsAnalyzer", + "ActivationSequenceAnalyzer", "ProgressAnalyzer" ] }, "disabled_analyzers": [ + "ActivityMapper", "LocomotionActionAnalyzer", "LogEntryCountAnalyzer", "LocationAnalyzer", @@ -59,14 +65,15 @@ "action":"PAUSE" } }, - "host":"http://0.0.0.0:5000", + "host":"http://potato.kinf.wiai.uni-bamberg.de:5000", + "host2":"http://potato.kinf.wiai.uni-bamberg.de:5000", "coordinates": "location.coordinates" }, "source":{ "type": "Biogames", - "url": "http://0.0.0.0:5000/game2/instance/log/list/", - "login_url": "http://localhost:5000/game2/auth/json-login", - "username": "dev", - "password": "dev" + "url": "http://potato.kinf.wiai.uni-bamberg.de:5000/game2/instance/log/list/", + "login_url": "http://potato.kinf.wiai.uni-bamberg.de:5000/game2/auth/json-login", + "username": "lb", + "password": "81743" } } \ No newline at end of file diff --git a/log_analyzer.py b/log_analyzer.py index d650e7f..ff25e77 100644 --- a/log_analyzer.py +++ b/log_analyzer.py @@ -16,7 +16,7 @@ requests_log.setLevel(logging.WARN) def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]: - logfile: str = "data/inst_{id}.{format}".format(id=log_id, format=settings.log_format) + logfile: str = "data/urach/inst_{id}.{format}".format(id=log_id, format=settings.log_format) loader = LOADERS[settings.log_format]() try: loader.load(logfile) @@ -37,12 +37,94 @@ def process_log(log_id: str, settings: LogSettings) -> List[Analyzer]: if __name__ == '__main__': settings: LogSettings = load_settings("biogames2.json") log_ids: List[str] = [ - "20d4244719404ffab0ca386c76e4b112", - "56d9b64144ab44e7b90bf766f3be32e3", - "dc2cdc28ca074715b905e4aa5badff10", - "e32b16998440475b994ab46d481d3e0c", + "0ff5e4d75a7c4c5683dd025aaac7de0d", +"1d80340985c7411aa78f9629aef91351", +"02c537ce1a514cb09eb387e7993f51a4", +"2cf1f8a490ac45e7bb035acc2de6bbc9", +"2f1f7713a6324fe580dbc67d4254bda5", +"3b5e4a43472f468196cc6b6a26c984a5", +"4a6e165e1e85421aaa681a68b6448f6b", +"4a2079607e9f41e9a070b32bf5a6b321", +"4ad0de379b36424e91bc709139a2538f", +"4b52635a0473424da7f9593098a38b11", +"04bf6dbbf5f846ad8d505faea8be7f45", +"5a1ae8dfa1f34469b14e910f8794285d", +"5ca377951ae440c7b3c479dc6786da52", +"5dd7e3d04dce41279b14d32f42c2052d", +"6f6f2edb053b409197f77b0322fc2c10", +"7a5f314c866f4413ae3a9eb5a0bd544a", +"7b25d0c0d2a44d31a93b8c8a84ea9cbb", +"7b697ac0aa1a480698261b62807cd447", +"7c7e3b819ec44b2994dadfad40508d56", +"7c7860ecf8904a57ad8829298570382e", +"7d96db101a254161b30078b421e5c4e2", +"09a641efdb6e47a4b7be5ef697d57cee", +"9c08fb690c5e42ec8add80305c78476a", +"9c699184e5314c5192000b998912f9c3", +"34eff87a077a45cdb64a0b1001098d16", +"35a755e2c73c48dda77f32c1e65c16c5", +"36c686cc3493405c8ce3df9f0b9e9f0b", +"36e350a44a744e08b491cef368c92aae", +"39e9e1625a7a426f81b387e56a142ea3", +"46d18a1237e34e689eeb47a24bd1f1a7", +"46fdee17dffe4e4b9ac3dd9dee7d3860", +"52ded2824b6c40559a923fc772148a8d", +"59bcafe4041d4c919585bac2be39fbe4", +"63e1a33bb1bd474bb8cffe6af54f6fe2", +"63fb0ee5bdd74c9d8d1a11958e6cbcc0", +"74f47e7694cf4bd2b965790479d5c4e6", +"76a20e83af5d4edab295f4f93d436c1c", +"0080e8e0364d4ed69fb349f95810ca4e", +"122a2dbc4aa94fd9a5535385a4c5c624", +"173c95bca9024eb5897d6f196d7b35e3", +"203f9b1e3113486c87dee0cc7ab2ec3e", +"292cf93f6ad147b5babbe9fd0842672d", +"510f86e65deb43bdad3f30ca55366fa7", +"683a0ab03fee437790ea06770e850f0d", +"698a03dca3ab41969c5ba91c4ac95012", +"788ddde1fa5e49498363907f54ab525f", +"798a8620c6aa4a369d31cf07357176e8", +"974c98d5426446c9af6be608d69e8cea", +"977cd2ae146e4b5cb53b284c5b58bee6", +"1887ed68b88f49a686d8d433b7f439a0", +"1307199d0d4f4f8f8dd019fa7e4dc9a8", +"58865640dc73482984f08b5ef728683c", +"83150656b4cf47409c2a8c971d78c359", +"a17f6affa68140aaaaded61c7dd310e0", +"a39c7ff84f624237a8e649b56577aedc", +"a85e76d834d64fc4986e6eea45cf48cf", +"a3549e5a2f5e4bcea5af97af0e86ea60", +#"a57903d4d27b47a0afa4f198a7bf9741", +"b1cf964e987f4387a3c377c329623a89", +"b59d67957ea946ecab7ce57ba395f825", +"b606f8c1c00e4edb8fe8e3afc6b790cb", +"b55222002dff47afb9cde94deb2d776f", +"b845757019654c20bf4f11a8aa2964f4", +"bac9268aca25471587a274baa8cb0aef", +"c999941878a04ca4b96b00308fdf1d47", +"d0e41604aa1c4a50a06fdc867e3e0883", +"d2c2a43cce4a4ebfa7008423e108fff4", +"d20c062e155147af9aaaee477e68e209", +"d31b742005d04f8e85845ad0fb9582fc", +"d6821c791abd40cf9d90ebf01ce287b8", +"d49515a15647455db263a5b1a963bb5d", +"da2ecef74b0b42dfb4599aa231580dcf", +"dbb281fdff3849eeb7ff61d343172dd9", +"dbd5e5ea53bf4f5db3dd99582322f915", +"de8a9a1996934ae98daa93dc2425509f", +"e0c802e9e50146fc93346d0f6e865612", +"e6b34adce1534ae08af70613c0ef729d", +"e55630984dcb4b87aa13080d0ef23e15", +"eed665d75dfa4a619d5a74a6cc104341", +"f7d0033ee7124baf974f171a571e5e0a", +"f303f2c550704a178b7c56417d44c329", +"f1106d463759429e8a4dda41fda512f8", +"f8045427e89349deb279d3c12e9c0462", +"feb8cf484f604e4a8137a8d00e7226b8", +"ff935be0480c4c6cac56ebff9021895f", +"ffae0d9d78124b6f808cef1771e78179", ] - log_ids: List[str] = [ + #log_ids: List[str] = [ #"34fecf49dbaca3401d745fb467", # "44ea194de594cd8d63ac0314be", # "57c444470dbf88605433ca935c", @@ -52,10 +134,11 @@ if __name__ == '__main__': # "e01a684aa29dff9ddd9705edf8", # "fbf9d64ae0bdad0de7efa3eec6", # "fe1331481f85560681f86827ec", - "fe1331481f85560681f86827ec"] + # "fe1331481f85560681f86827ec"] #"fec57041458e6cef98652df625", ] store: ResultStore = ResultStore() for log_id in log_ids: + log.debug(log_id) for analysis in process_log(log_id, settings): log.info("* Result for " + analysis.name()) # print(analysis.result()) @@ -67,9 +150,20 @@ if __name__ == '__main__': if False: render(analyzers.LocationAnalyzer, store.get_all()) #print(json.dumps(store.serializable(), indent=1)) - if True: + if False: render(analyzers.ActivityMapper, store.get_all()) render(analyzers.ProgressAnalyzer, store.get_all()) + if True: + for a in [analyzers.BiogamesCategorizer, + analyzers.ActivityMapper, + analyzers.LogEntrySequenceAnalyzer, + analyzers.ActionSequenceAnalyzer, + analyzers.BoardDurationAnalyzer, + analyzers.LocomotionActionAnalyzer, + analyzers.SimulationRoundsAnalyzer, + analyzers.ProgressAnalyzer]: + print(str(a)) + render(a, store.get_all()) # for analyzers in analyzers: # if analyzers.name() in ["LogEntryCount", "ActionSequenceAnalyzer"]: diff --git a/util/download.py b/util/download.py index f0f2998..daa9d48 100644 --- a/util/download.py +++ b/util/download.py @@ -7,6 +7,8 @@ logger = logging.getLogger(__name__) def download_board(board_id, host, instance_config_id, sequence_id, source): + if sequence_id is None: + return "static" local_file = "static/progress/images/{config_id}/{sequence_id}/{board_id}".format( config_id=instance_config_id, sequence_id=sequence_id, @@ -21,7 +23,9 @@ def download_board(board_id, host, instance_config_id, sequence_id, source): ) board = source._get(url) if not board.ok: - raise ConnectionError() + #raise ConnectionError() + logger.error("HTTP FAIL:", board) + return "static" data = board.json() preview_url = json_path(data, "preview_url.medium") logger.debug(preview_url)