class SettingsWindow(BaseWidget): def __init__(self, *args, **kwargs): global settings_json BaseWidget.__init__(self, "Settings") self._settingslabel = ControlLabel("Settings") self._outputfolder = ControlText("SD Card Path") self._outputfolder.value = settings_json["outputfolder"] self._hmackey = ControlText("Capsrv HMAC Secret") self._hmackey.value = settings_json["hmackey"] self._customgameid = ControlText("Custom Game ID") self._customgameid.value = settings_json["customgameid"] self._typelabel = ControlLabel("Type") self._imagecheckbox = ControlCheckBox("Image") self._imagecheckbox.value = (settings_json["type"] == "image") self._imagecheckbox.changed_event = self.imageCheckbox self._mangacheckbox = ControlCheckBox("Manga") self._mangacheckbox.value = (settings_json["type"] == "manga") self._mangacheckbox.changed_event = self.mangaCheckbox self._comiccheckbox = ControlCheckBox("Comics") self._comiccheckbox.value = (settings_json["type"] == "comics") self._comiccheckbox.changed_event = self.comicCheckbox self._directionlabel = ControlLabel("Direction") self._directionlabel.hide() self._lefttoright = ControlCheckBox("From left to right") self._lefttoright.hide() self._lefttoright.value = (settings_json["direction"] == "ltr") self._lefttoright.changed_event = self.fromLeftToRight self._righttoleft = ControlCheckBox("From right to left") self._righttoleft.hide() self._righttoleft.value = (settings_json["direction"] == "rtl") self._righttoleft.changed_event = self.fromRightToLeft self._savebutton = ControlButton("Save") self._savebutton.value = self.saveButton self.formset = [("_settingslabel"), ("_outputfolder"), ("_hmackey"), ("_customgameid"), ("_typelabel"), ("_imagecheckbox", "_mangacheckbox", "_comiccheckbox"), ("_directionlabel"), ("_lefttoright", "_righttoleft"), (" "), (" ", " ", "_savebutton")] self._typerequested = False self._directionrequested = False #Reimplementing radio buttons sure is fun def imageCheckbox(self): if self._typerequested: return self._typerequested = True self._mangacheckbox.value = False self._comiccheckbox.value = False self._imagecheckbox.value = True self._directionlabel.hide() self._lefttoright.hide() self._righttoleft.hide() self._typerequested = False def comicCheckbox(self): if self._typerequested: return self._typerequested = True self._mangacheckbox.value = False self._comiccheckbox.value = True self._imagecheckbox.value = False self._directionlabel.show() self._lefttoright.show() self._righttoleft.show() self._typerequested = False def mangaCheckbox(self): if self._typerequested: return self._typerequested = True self._mangacheckbox.value = True self._comiccheckbox.value = False self._imagecheckbox.value = False self._directionlabel.show() self._lefttoright.show() self._righttoleft.show() self._typerequested = False def fromLeftToRight(self): if self._directionrequested: return self._directionrequested = True self._lefttoright.value = True self._righttoleft.value = False self._directionrequested = False def fromRightToLeft(self): if self._directionrequested: return self._directionrequested = True self._lefttoright.value = False self._righttoleft.value = True self._directionrequested = False def saveButton(self): global settings_json typ = "" if not self._mangacheckbox.value and not self._comiccheckbox.value: typ = "image" elif self._mangacheckbox.value: typ = "manga" else: typ = "comics" direction = "" if not self._righttoleft.value: direction = "ltr" else: direction = "rtl" try: a = bytes.fromhex(self._hmackey.value) if (len(a) != 0x20 or sha256(a).hexdigest( ) != "e9735dae330300b8bb4b5892c8178f5d57daa32d7b5ef5d15f14491800ce4750" ): raise except: self.alert("Invalid HMAC key!", "Error!") return try: a = bytes.fromhex(self._customgameid.value) if (len(a) != 16) and self._customgameid.value != "": raise ValueError if (self._customgameid.value == ""): raise except ValueError: self.alert("Invalid custom game ID!", "Error!") return except: self._customgameid.value = "57B4628D2267231D57E0FC1078C0596D" if self._outputfolder.value == "": self._outputfolder.value = "." settings_json = { "outputfolder": self._outputfolder.value, "hmackey": self._hmackey.value, "customgameid": self._customgameid.value, "type": typ, "direction": direction } json.dump( settings_json, open( appdirs.AppDirs("NSScreenshotMaker", "").user_data_dir + "/settings.json", "w"))
class HeatMapApp(BaseApp): """Application form""" def __init__(self, title='Heat map'): super(HeatMapApp, self).__init__(title) self._heatmapImg = None #Store a numpy array with the heatmap self._velocities = None #Store the velocities for each frame self._accelerations = None #Store the accelarations for each frame ##### CONTROLS ############################################################################## self._heatmap = ControlVisVisVolume("Volume") self._toggleSphereVisibility = ControlButton('Filter by a region', checkable=True) self._sphere = ControlText('Position filter (x,y,z,radius)') self._toggleHeatmapVars = ControlButton('Select variables', checkable=True) self._heatmapVarsBnds = ControlBoundingSlider('Variable bounds', horizontal=True) self._heatmapHigherVarsValues = ControlCheckBox( 'Most higher', helptext='Show only the higher values') self._heatmapColor = ControlCombo('Color map') self._apply2Heatmap = ControlButton('Apply to map') self._heatmapColorsBnds = ControlBoundingSlider('Colors', horizontal=False) self._heatmapVarsList = ControlCombo('Variables') self._heatmapVars = ControlCheckBox('Map variables') self._heatMapMinVar = ControlText('Min vel.') self._heatMapMaxVar = ControlText('Max vel.') ############################################################################################# self._modules_tabs.update({ 'Heat map': [('_heatmapColor', ' | ', 'Filters:', '_toggleHeatmapVars', '_toggleSphereVisibility', '_sphere', ' | ', '_apply2Heatmap', ' '), ('_heatmapVarsList', '_heatmapVars', '_heatmapHigherVarsValues', '_heatMapMinVar', '_heatmapVarsBnds', '_heatMapMaxVar'), { 'Map': ('_heatmap', '_heatmapColorsBnds') }] }) ############################################################################################# self._heatmapVarsList += 'Velocity' self._heatmapVarsList += 'Acceleration' self._heatmapColor.add_item('Bone', vv.CM_BONE) self._heatmapColor.add_item('Cool', vv.CM_COOL) self._heatmapColor.add_item('Copper', vv.CM_COPPER) self._heatmapColor.add_item('Gray', vv.CM_GRAY) self._heatmapColor.add_item('Hot', vv.CM_HOT) self._heatmapColor.add_item('HSV', vv.CM_HSV) self._heatmapColor.add_item('Jet', vv.CM_JET) self._heatmapColor.add_item('Pink', vv.CM_PINK) self._heatmapColor.add_item('Autumn', vv.CM_AUTUMN) self._heatmapColor.add_item('Spring', vv.CM_SPRING) self._heatmapColor.add_item('Summer', vv.CM_SUMMER) self._heatmapColor.add_item('Winter', vv.CM_WINTER) self._heatmapColor.value = vv.CM_HSV self._sphere.hide() self._heatmapVarsBnds.hide() self._heatmapVarsList.hide() self._heatMapMinVar.hide() self._heatMapMaxVar.hide() self._heatmapVars.hide() self._heatmapHigherVarsValues.hide() self._heatmapVarsBnds.convert_2_int = False self._heatmapColorsBnds.convert_2_int = False self._apply2Heatmap.value = self.calculate_heatmap_event self._heatmapColor.changed = self.changed_heatmap_color_event self._toggleSphereVisibility.value = self.__toggle_sphere_visiblity_event self._toggleHeatmapVars.value = self.__toggle_variables_visibility_event self._heatmapVarsList.changed = self.__changed_heatmap_variables_list_event self._heatMapMinVar.changed = self.__changed_heatmap_minVar_event self._heatMapMaxVar.changed = self.__changed_heatmap_maxVar_event self._heatmapColorsBnds.changed = self.changed_heatmap_colors_bounds_event self._heatmapVars.changed = self.__changed_heatmap_variables_event ############################################################################################ ### AUXILIAR FUNCTIONS ##################################################################### ############################################################################################ def __calc_heatmap_size(self, x_diff, y_diff, z_diff, scale=None): """ Calculate the heatmap size """ if scale == None: scale = self.fit_scale(x_size, y_size, z_size) x_scaled_size = int(round((x_diff + 1) * scale)) y_scaled_size = int(round((y_diff + 1) * scale)) z_scaled_size = int(round((z_diff + 1) * scale)) return x_scaled_size, y_scaled_size, z_scaled_size def fit_scale(self, x_diff, y_diff, z_diff): """ Calculate the scale value that should be applied to each position, so they can fit in an numpy array """ scale = 1.0 new_scale = 1.0 x_size, y_size, z_size = 0, 0, 0 #The maximum allowed size for the heatmap is (2000,2000,2000) while x_size <= 2000.0 and y_size <= 2000.0 and z_size <= 2000.0: scale = new_scale new_scale = scale * 10.0 x_size, y_size, z_size = self.__calc_heatmap_size( x_diff, y_diff, z_diff, new_scale) return scale ############################################################################################ ### EVENTS ################################################################################# ############################################################################################ def __changed_heatmap_variables_event(self): if self._heatmapVars.value: self._heatmapHigherVarsValues.show() else: self._heatmapHigherVarsValues.hide() def __toggle_sphere_visiblity_event(self): if self._toggleSphereVisibility.checked: self._sphere.show() else: self._sphere.hide() def __toggle_variables_visibility_event(self): if self._toggleHeatmapVars.checked: self._heatmapVarsList.show() self._heatmapVarsBnds.show() self._heatMapMinVar.show() self._heatMapMaxVar.show() self._heatmapVars.show() else: self._heatmapVarsList.hide() self._heatmapVarsBnds.hide() self._heatMapMinVar.hide() self._heatMapMaxVar.hide() self._heatmapVars.hide() def changed_heatmap_colors_bounds_event(self): if self._heatmapImg is None or not self._heatmapImg.any(): return self._heatmap.colors_limits = self._heatmapColorsBnds.value def __changed_heatmap_minVar_event(self): if self._heatMapMinVar.value == '': return v = eval(self._heatMapMinVar.value) self._heatmapVarsBnds.min = v values = list(self._heatmapVarsBnds.value) if values[0] < v: values[0] = v self._heatmapVarsBnds.value = values def __changed_heatmap_maxVar_event(self): if self._heatMapMaxVar.value == '': return v = eval(self._heatMapMaxVar.value) self._heatmapVarsBnds.max = v values = list(self._heatmapVarsBnds.value) if values[1] > v: values[1] = v self._heatmapVarsBnds.value = values def __changed_heatmap_variables_list_event(self): if self._heatmapVarsList.value == 'Velocity' and self._velocities: lower = int(0 if self._boundings.value[0] < 0 else self._boundings. value[0]) higher = int( len(self._velocities) if self._boundings.value[1] >= len( self._velocities) else self._boundings.value[1]) max_val = max(self._velocities[lower:higher]) min_val = min(self._velocities[lower:higher]) self._heatmapVarsBnds.value = round(min_val, 2), round(max_val, 2) self._heatMapMinVar.value = str( round(min_val - (max_val - min_val) * 0.1, 2)) self._heatMapMaxVar.value = str( round(max_val + (max_val - min_val) * 0.1, 2)) if self._heatmapVarsList.value == 'Acceleration' and self._accelerations: lower = int(0 if self._boundings.value[0] < 0 else self._boundings. value[0]) higher = int( len(self._accelerations) if self._boundings.value[1] > (len(self._accelerations) + 1) else self._boundings.value[1]) max_val = max(self._accelerations[lower:higher]) min_val = min(self._accelerations[lower:higher]) self._heatmapVarsBnds.value = round(min_val, 2), round(max_val, 2) self._heatMapMinVar.value = str( round(min_val - (max_val - min_val) * 0.1, 2)) self._heatMapMaxVar.value = str( round(max_val + (max_val - min_val) * 0.1, 2)) def changed_heatmap_color_event(self): self._heatmap.colorMap = self._heatmapColor.value ############################################################################################ ### Map generation ######################################################################### ############################################################################################ def calculate_heatmap_event(self): #Filter for the data from a lower and upper frame if self._data is None: return self._progress.min = lower = 0 if self._boundings.value[0] < 0 else int( self._boundings.value[0]) self._progress.max = higher = len( self._data) if self._boundings.value[1] > ( len(self._data) + 1) else int(self._boundings.value[1]) #Calculate the size of the map x_diff = self._data.xRange[1] - self._data.xRange[0] y_diff = self._data.yRange[1] - self._data.yRange[0] z_diff = self._data.zRange[1] - self._data.zRange[0] scale = self.fit_scale(x_diff, y_diff, z_diff) #Fit the best scale value x_size, y_size, z_size = self.__calc_heatmap_size( x_diff, y_diff, z_diff, scale) #Return the best size for the map image try: sphere = sphere_x, sphere_y, sphere_z, sphere_r = eval( self._sphere.value) except: sphere = None min_var, max_var = self._heatmapVarsBnds.value which_var = 0 if self._heatmapVarsList.value == 'Velocity' else 1 #Create the map image img = np.zeros((z_size, x_size, y_size), dtype=np.float32) for i in range(lower, higher): if (i % 3000) == 0: self._progress.value = i if self._data[i] != None: position = self._data[i].position #shift and scale the coordenates, to avoid negative and decimal values #is only possible to map in the image positive and integer coordenates x, y, z = position x += abs(self._data.xRange[0]) y += abs(self._data.yRange[0]) z += abs(self._data.zRange[0]) x = int(round(x * scale)) y = int(round(y * scale)) z = int(round(z * scale)) #Filter position by a defined sphere if sphere != None and lin_dist3d( (x, y, z), (sphere_x, sphere_y, sphere_z)) > sphere_r: continue #Use variables to construct the map, or positions if self._toggleHeatmapVars.checked: #velocities array has less 1 element than positions array if which_var == 0 and len(self._velocities) <= i: continue #accelarations array has less 2 element than positions array if which_var == 1 and len(self._accelerations) <= i: continue var = self._velocities[ i] if which_var == 0 else self._accelerations[i] #Filter by variable boundaries if not (min_var <= var <= max_var): continue if self._heatmapVars.value: #Map the variables if self._heatmapHigherVarsValues.value: tmp = img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] tmp[tmp < var] = var else: img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += var else: #Map positions img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += 1.0 else: #Map positions img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += 1.0 self._progress.value = higher color_min = np.min(img) color_max = np.max(img) self._heatmapColorsBnds.min = color_min - (color_max - color_min) * 0.1 self._heatmapColorsBnds.max = color_max + (color_max - color_min) * 0.1 self._heatmapColorsBnds.value = color_min, color_max self._heatmap.value = np.zeros((1, 1), dtype=np.float32) self._heatmap.colors_limits = None self._heatmap.value = img self._heatmapImg = img ############################################################################################ ### CLASS OVERRIDE FUNCTIONS ############################################################### ############################################################################################ def frames_boundings_changed(self): super(HeatMapApp, self).frames_boundings_changed() self.__changed_heatmap_variables_list_event() def load_tracking_file(self): super(HeatMapApp, self).load_tracking_file() self.__changed_heatmap_variables_list_event() def export_tracking_file(self): filename, _ = QFileDialog.getSaveFileName(self, 'Select a file', selectedFilter='*.csv') if not filename: return filename = str(filename) if not filename.lower().endswith('.csv'): filename += '.csv' #Export only the selected bounds lower = 0 if self._boundings.value[0] < 0 else self._boundings.value[0] higher = len(self._data) if self._boundings.value[1] > ( len(self._data) + 1) else self._boundings.value[1] self._progress.min = lower self._progress.max = higher which_var = 0 if self._heatmapVarsList.value == 'Velocity' else 1 try: sphere = sphere_x, sphere_y, sphere_z, sphere_r = eval( self._sphere.value) except: sphere = None min_var, max_var = self._heatmapVarsBnds.value #Calculate the size of the map x_diff = self._data.xRange[1] - self._data.xRange[0] y_diff = self._data.yRange[1] - self._data.yRange[0] z_diff = self._data.zRange[1] - self._data.zRange[0] scale = self.fit_scale(x_diff, y_diff, z_diff) #Fit the best scale value with open(filename, 'wb') as csvfile: spamwriter = csv.writer(csvfile, delimiter=',') for i in range(int(lower), int(higher)): self._progress.value = i position = self._data[i].position x, y, z = position x += abs(self._data.xRange[0]) y += abs(self._data.yRange[0]) z += abs(self._data.zRange[0]) x = int(round(x * scale)) y = int(round(y * scale)) z = int(round(z * scale)) if sphere != None and lin_dist3d( (x, y, z), (sphere_x, sphere_y, sphere_z)) > sphere_r: continue if self._toggleHeatmapVars.checked: var = self._velocities[ i] if which_var == 0 else self._accelerations[i] if not (min_var <= var <= max_var): continue if self._data[i] == None: continue row2save = self._data[i].row if i > lower: row2save = row2save + [self._velocities[i]] if (i + 1) > lower: row2save = row2save + [self._accelerations[i]] spamwriter.writerow(row2save)