def arrays_to_heatmap(numpy_arrays, gaussian_size, clip): """Convert list of arrays into a heatmap. The stages and values are chosen with trial and error, so this function is still open to improvement. """ #Add all arrays together _print('Merging arrays...') merged_arrays = numpy.merge(numpy_arrays, 'add', 'float64') #Set to constant values _print('Flattening values...') flattened = numpy.remap_to_range(merged_arrays) #Blur the array if gaussian_size: _print('Applying gaussian blur...') heatmap = blur(flattened, gaussian_size) else: heatmap = flattened _print('Finding range limits...') min_value = numpy.min(heatmap) #Lower the maximum value a little all_values = numpy.sort(heatmap.ravel(), unique=True) max_value = all_values[round_int(all_values.size * clip)] return ((min_value, max_value), heatmap)
def gaussian_size(width, height): """Calculate correct size of gaussian blur. Currently only height is taken into account, but this could change, so takes both values. """ gaussian_base = CONFIG['GenerateHeatmap']['_GaussianBlurBase'] gaussian_mult = CONFIG['GenerateHeatmap']['GaussianBlurMultiplier'] try: return round_int(height * gaussian_base * gaussian_mult) except TypeError: raise ValueError('invalid input type, must be int')
def fix_poe_mine_build(profile_name, numpad_key): try: _num = 'NUM{}'.format(int(numpad_key)) except ValueError: return False data = LoadData(profile_name, _reset_sessions=False) #Make sure record exists, quick delete if issue is obvious (0 press >0 held) try: if not data['Keys']['All']['Pressed'][_num]: raise KeyError except KeyError: try: del data['Keys']['All']['Held'][_num] except KeyError: pass else: #Count the other numpad items total = {'pressed': 0, 'held': 0, 'count': 0} for i in range(1, 10): if i == numpad_key: continue num = 'NUM{}'.format(i) try: total['pressed'] += data['Keys']['All']['Pressed'][num] total['held'] += data['Keys']['All']['Held'][num] except KeyError: pass else: total['count'] += 1 #Get the average time the numpad is pressed for try: average_press_time = total['held'] / total['pressed'] except ZeroDivisionError: average_press_time = 0 Message('Unable to get an average as no other keypad data exists.') result = input( 'Do you want to delete the numpad key instead (y/n)? ') if not is_yes(result): return False #Assign to numpad key new_held_time = round_int(data['Keys']['All']['Pressed'][_num] * average_press_time) data['Keys']['All']['Held'][_num] = new_held_time return save_data(profile_name, data)
from PIL import Image, ImageFont, ImageDraw from core.image.colours import COLOUR_FILE, ColourRange, calculate_colour_map, get_luminance, parse_colour_file from core.compatibility import get_items, range, Message from core.config import CONFIG from core.language import Language from core.files import load_data from core.maths import round_int, calculate_circle from core.messages import ticks_to_seconds MULTIPLIER = CONFIG['GenerateKeyboard']['SizeMultiplier'] if CONFIG['GenerateImages']['HighPrecision']: MULTIPLIER = max(4, MULTIPLIER) KEY_SIZE = round_int(CONFIG['Advanced']['KeyboardKeySize'] * MULTIPLIER) KEY_CORNER_RADIUS = round_int(CONFIG['Advanced']['KeyboardKeyCornerRadius'] * MULTIPLIER) KEY_PADDING = round_int(CONFIG['Advanced']['KeyboardKeyPadding'] * MULTIPLIER) KEY_BORDER = round_int(CONFIG['Advanced']['KeyboardKeyBorder'] * MULTIPLIER) DROP_SHADOW_X = round_int(CONFIG['Advanced']['KeyboardDropShadowX'] * MULTIPLIER) DROP_SHADOW_Y = round_int(CONFIG['Advanced']['KeyboardDropShadowY'] * MULTIPLIER) IMAGE_PADDING = round_int(CONFIG['Advanced']['KeyboardImagePadding'] *
def generate(self, image_type, reload=False): image_type = image_type.lower() if reload: self.reload() lookup = {'clicks': 'GenerateHeatmap', 'tracks': 'GenerateTracks', 'keyboard': 'GenerateKeyboard', 'csv-tracks': 'NameFormatTracks', 'csv-clicks': 'NameFormatClicks', 'csv-keyboard': 'NameFormatKeyboard'} try: name = CONFIG[lookup[image_type]]['NameFormat'] except KeyError: try: name = CONFIG['GenerateCSV'][lookup[image_type]] except KeyError: raise ValueError('incorred image type: {}'.format(image_type)) #Rename alternative variables for k, v in get_items(self.ALTERNATIVES): k = '[{}]'.format(k) for i in v: i = '[{}]'.format(i) name = name.replace(i, k) #General Options name = name.replace('[Name]', self.name) name = name.replace('[FileName]', self.file_name) name = name.replace('[Width]', self.width) name = name.replace('[Height]', self.height) name = name.replace('[UpscaleWidth]', self.uwidth) name = name.replace('[UpscaleHeight]', self.uheight) name = name.replace('[Version]', VERSION) name = name.replace('[HighPrecision]', self.high_precision) if self.data is not None: name = name.replace('[FirstSave]', str(round_int(self.data['Time']['Created']))) name = name.replace('[LatestSave]', str(round_int(self.data['Time']['Modified']))) name = name.replace('[FileVersion]', str(self.data['Version'])) name = name.replace('[TimesLoaded]', str(self.data['TimesLoaded'])) name = name.replace('[Sessions]', str(len(self.data['SessionStarts']))) ticks = self.data['Ticks']['Total'] name = name.replace('[Ticks]', str(int(ticks))) name = name.replace('[RunningTimeSeconds]', str(round_int(ticks / UPDATES_PER_SECOND))) name = name.replace('[RunningTimeMinutes]', str(round(ticks / (UPDATES_PER_SECOND * 60), 2))) name = name.replace('[RunningTimeHours]', str(round(ticks / (UPDATES_PER_SECOND * 60 * 60), 2))) name = name.replace('[RunningTimeDays]', str(round(ticks / (UPDATES_PER_SECOND * 60 * 60 * 24), 2))) #Specific options if image_type == 'clicks': name = name.replace('[Colours]', self.heatmap_colours) name = name.replace('[MouseButton]', self.heatmap_button_group) name = name.replace('[GaussianBlur]', self.heatmap_gaussian) name = name.replace('[GaussianSigma]', self.heatmap_gaussian_actual) elif image_type == 'tracks': name = name.replace('[Colours]', self.track_colour) elif image_type.lower() == 'keyboard': name = name.replace('[Exponential]', self.keyboard_exponential) name = name.replace('[Colours]', self.keyboard_colour) name = name.replace('[DataSet]', self.keyboard_set) name = name.replace('[Size]', self.keyboard_size_mult) name = name.replace('[Extended]', self.keyboard_extended) elif image_type.startswith('csv'): if image_type == 'csv-clicks': #Using the heatmap mouse buttons saves rewriting parts of the function, #but the config will need edited first to only have one button selected. name = name.replace('[MouseButton]', self.heatmap_button_group) else: raise ValueError('incorred image type: {}'.format(image_type)) #Replace invalid characters invalid_chars = ':*?"<>|' for char in invalid_chars: if char in name: name = name.replace(char, '') if image_type.startswith('csv'): ext = 'csv' else: ext = CONFIG['GenerateImages']['FileType'] return '{}.{}'.format(format_file_path(name), ext)