import time import logging from datetime import datetime from collections import defaultdict from pylab import plt, date2num, title, axvline from matplotlib import dates import numpy as np from scipy.misc import pilutil from PIL import ImageDraw, Image, ImageFilter from intersect import Mesh2D from utils.objparser import Mesh from utils import pos2rgb from utils.tiles import createLog2Tiles log = logging.getLogger('lws') ## the plot functions are not threadsafe ## the locking has to be done at the call site def plotOptimizeRun(lines, destfile, xaxis='date', highlightmins=True): xaxis = '' currmin = 10**9 freeparams = defaultdict(list) orgidx = [] avgdeltas = [] dts = [] simsperhour = defaultdict(int) mins_idx = [] for j, l in enumerate(lines): if j % 500 == 0: log.debug('processing line %s of %s' % (j, len(lines))) for i, e in enumerate(l.split()): if i == 0: dt = datetime.strptime(e, '%Y-%m-%dT%H:%M:%S') simsperhour[dt.day * 24 + dt.hour] += 1 # will break at months end dts.append(dt) elif e.startswith('gen:'): pass elif e.startswith('org:'): #~ orgidx.append(int(e[4:])) pass elif e.startswith('avg-delta:'): v = float(e[10:]) avgdeltas.append(v) if v < currmin: if xaxis == 'date': mins_idx.append(dt) else: mins_idx.append(j) currmin = v else: name, values = e.split(':') if ',' in values: freeparams[name].append([float(v) for v in values.split(',')]) else: freeparams[name].append(float(values)) if xaxis == 'date': xs = date2num(dts) mins_idx = date2num(mins_idx) else: xs = range(len(lines)) min_x, max_x = min(xs), max(xs) # HACK: FILTER DA-PARAMS freeparams = {k:v for k, v in freeparams.items() if not k.startswith('da/')} numcols = 3 fig = plt.figure(figsize=(18, len(freeparams) * 3.0 / numcols)) # 20x15 inches numrows = (len(freeparams) + 2) / numcols + 1 if len(xs) < 1000: POINT_SIZE = 5 elif len(xs) < 10000: POINT_SIZE = 3 else: POINT_SIZE = 2 ax = fig.add_subplot(numrows, numcols, 1) if highlightmins: plotfunc = lambda ax: ax.scatter kwargs = dict(s=POINT_SIZE, alpha=0.8, linewidth=0) else: plotfunc = lambda ax: ax.plot kwargs = dict() ax.grid() plotfunc(ax)(xs, avgdeltas, color='blue', **kwargs) ax.set_xlim(min_x, max_x) if xaxis == 'date': ax.xaxis_date() ax.xaxis.set_major_formatter(dates.DateFormatter('%H:%M')) for xtl in ax.get_xticklabels(): xtl.set_fontsize(8) title('average delta' ) if highlightmins: for m in mins_idx: axvline(m, color='black', linewidth=0.5) ax = fig.add_subplot(numrows, numcols, 2) xs_h, ys = zip(*list(sorted(simsperhour.items()))) ax.grid() m = min(xs_h) ax.bar([x - m for x in xs_h], ys) title('sims per hour (all aps)') for i, (name, values) in enumerate(sorted(freeparams.items()), 1): ax = fig.add_subplot(numrows, numcols, 2 + i) ax.grid() ax.set_xlim(min_x, max_x) if name.startswith('da/'): plotfunc(ax)(xs, values, **kwargs) if name.startswith('n/'): plotfunc(ax)(xs, values, **kwargs) elif isinstance(values[0], float): # it's a power value ax.set_yscale('log') plotfunc(ax)(xs, values, **kwargs) ax.set_ylim(min(values)*0.5, max(values)*2) else: reflect, alpha = zip(*values) plotfunc(ax)(xs, reflect, color='blue', **kwargs) plotfunc(ax)(xs, alpha, color='green', **kwargs) ax.set_ylim(0, 1) if xaxis == 'date': ax.xaxis_date() ax.xaxis.set_major_formatter(dates.DateFormatter('%H:%M')) for xtl in ax.get_xticklabels(): xtl.set_fontsize(8) title(name, y=0.95, fontsize=10, backgroundcolor='#EFEFEF') if highlightmins: for m in mins_idx: axvline(m, color='black', linewidth=0.5, alpha=0.6) fig.subplots_adjust(bottom=0.05, left=0.03, right=0.99, top=0.98) fig.savefig(destfile, format='png', dpi=90) plt.close(fig) def plotSimulatorStats(lines, destfile): LAST_HOURS = 12 fig = plt.figure(figsize=(18, 12)) xs = [] waiting = [] running = [] finished = [] last_waiting = 0 generations = defaultdict(int) simulations = defaultdict(int) for l in lines: data = l.split() ts = float(data[1]) if time.time() - ts > LAST_HOURS * 3600: continue dt = datetime.fromtimestamp(ts) curr_hour = dt.replace(minute=0, second=0, microsecond=0) xs.append(dt) w = int(data[3]) waiting.append(w) if w > last_waiting: generations[curr_hour] += 1 last_waiting = w simulations[curr_hour] += 1 running.append(int(data[5])) finished.append(int(data[7])) xs = date2num(xs) for i, (datadict, name) in enumerate(((generations, 'generations/hour'), (simulations, 'simulations/hour')), 1): ax = fig.add_subplot(5, 1, i) ax.xaxis_date() _xs = date2num(datadict.keys()) ax.set_xlim(min(_xs), max(_xs)+1/24.0) ax.bar(_xs, datadict.values(), [1/24.0]*len(_xs)) title(name, y=0.95, fontsize=10, backgroundcolor='#EFEFEF') for i, (name, ys) in enumerate([('waiting', waiting), ('running', running), ('finished', finished)], 3): ax = fig.add_subplot(5, 1, i) ax.set_xlim(min(xs), max(xs)) ax.plot(xs, ys) ax.xaxis_date() title(name, y=0.95, fontsize=10, backgroundcolor='#EFEFEF') fig.subplots_adjust(bottom=0.05, left=0.03, right=0.99, top=0.98) fig.savefig(destfile, format='png', dpi=90) plt.close(fig) def plot2DMapAPData(lws, activeSceneCfg, env, apid): x1, x2, y1, y2, z1, z2 = activeSceneCfg['bbox'] pixel_per_meter = activeSceneCfg['2dpixelpermeter'] width = int((x2 - x1) * pixel_per_meter) * 8 height = int((y2 - y1) * pixel_per_meter) * 8 cube_size = int(0.2 * pixel_per_meter * 8) # in mapspace img = Image.new('RGBA', (width, height), color=(0, 0, 0, 0)) draw = ImageDraw.Draw(img) x_size, y_size, _ = env.aps[apid].dbdata.shape apcfg = lws.config['aps'][apid] _, _, z = env.translateToVoxel(apcfg['x'], apcfg['y'], apcfg['z']) max_rssi = env.aps[apid].dbdata[:,:, z].max() cut_off = -90 _, y_m, _ = env.translateToMeter(0, y_size, 0) _, y_map_max, _ = lws.intoMapSpace(0, y_m, 0) for x in range(x_size): for y in range(y_size): rssi = env.aps[apid].dbdata[x, y, z] if rssi < cut_off: continue x_m, y_m, z_m = env.translateToMeter(x, y, z) x_map, y_map, _ = lws.intoMapSpace(x_m, y_m, z_m) rgb = pos2rgb(-rssi+max_rssi*1.1, -cut_off + max_rssi, spread=0.7, saturation=0.7) draw.rectangle([x_map, y_map_max-y_map, x_map+cube_size, y_map_max-y_map+cube_size], fill=rgb) destfile = lws.config['tmp'].joinpath('apdatatiles_%s.png' % apid) img.save(destfile) destdir = lws.config['tmp'].joinpath('apdatatiles_%s' % apid) createLog2Tiles(destfile, destdir, logger=log, rgba=True) def plot2DMap(activeSceneCfg, level, locations, aps, destfile, refresh=False, customdraw=None, resizeFactor=1): z_cut = activeSceneCfg['levels2d'][level] - 0.50 objfile = activeSceneCfg['objfile'] x1, x2, y1, y2, _, _ = activeSceneCfg['bbox'] mesh = Mesh() mesh.parseObjFile(objfile) mesh_xlim = (int(x1), int(x2)) mesh_ylim = (int(y1), int(y2)) pixel_per_meter = activeSceneCfg['2dpixelpermeter'] m2d = Mesh2D(mesh, mesh_xlim, mesh_ylim, pixel_per_meter) log.info('building %s...' % level) if destfile.exists() and destfile.mtime > objfile.mtime and not refresh: if customdraw is not None: img = Image.open(destfile) img = img.convert('RGBA') draw = ImageDraw.Draw(img) customdraw(img, draw, m2d, z_cut, aps, locations) return to_be_combined = [] for objname in m2d.objnames: log.debug('object: %s' % objname) img = m2d.cut(objname, z_cut) to_be_combined.append(pilutil.fromimage(img)) all_objects = np.add.reduce(np.array(to_be_combined)) #~ combined_object_image log.info('save file to %s' % destfile.abspath()) img = pilutil.toimage(all_objects) img = img.convert('RGBA') draw = ImageDraw.Draw(img) for apid, apcfg in aps.items(): if abs(apcfg['z'] - z_cut) < 2: _x, _y = m2d.meter2pixel(apcfg['x'], apcfg['y']) draw.text((_x - 20, _y), apid, fill='#11CC11') draw.point((_x, _y), fill='#00FF00') for locid, loc in locations.items(): if -1.0 < (loc.z - z_cut) < 2.0: _x, _y = m2d.meter2pixel(loc.x, loc.y) draw.text((_x, _y), str(locid), fill='#CC1111') draw.point((_x, _y), fill='#00FF00') draw.text((10, 10), 'scene: %s level: %s' % (activeSceneCfg.name, level), fill='#FFFFFF') if resizeFactor != 1: log.info('resizing...') img = img.resize((int(img.size[0]*resizeFactor), int(img.size[1]*resizeFactor)), Image.ANTIALIAS) img.save(destfile) if customdraw is not None: img = Image.open(destfile) draw = ImageDraw.Draw(img) customdraw(img, draw, m2d, z_cut, aps, locations) def plotHistogram(destfile, data=None, format=None, title='', **kwargs): assert data is not None assert format in ('materials', ) fig = plt.figure(figsize=(15, 6)) ax = fig.add_subplot(1, 1, 1) #~ fig.subplots_adjust(bottom=0.2, left=0.03, right=0.99, top=0.98) if format == 'materials': dd = data.split('|') values2 = [] if ',' in dd[0]: values1 = [round(float(e.split(',')[0]), 2) for e in dd] ax.set_xlim((0, 1)) ax.hist(values1, color="blue", alpha=0.5) values2 = [round(float(e.split(',')[1]), 2) for e in dd] ax.hist(values2, color="green", alpha=0.5) title = title + '\n' + ','.join('%.2f' % e for e in sorted(values1)) + '\n' + ','.join('%.2f' % e for e in sorted(values2)) else: values1 = [float(e.split(',')[0]) for e in dd] title = title + '\n' + ','.join('%.1e' % e for e in sorted(values1)) ax.hist(values1) #~ else: #~ ax.set_xlim((0, 1)) ax.set_title(title, fontsize=8) fig.savefig(destfile, format='png', dpi=90) plt.close(fig)