def load_burst_from_json(self, **data): """Upload Burst from previously exported JSON file""" self.logger.debug("Uploading ..." + str(data)) try: upload_param = "uploadedfile" if upload_param in data and data[upload_param]: upload_param = data[upload_param] if isinstance(upload_param, FieldStorage) or isinstance(upload_param, Part): if not upload_param.file: raise BurstServiceException("Please select a valid JSON file.") upload_param = upload_param.file.read() upload_param = json.loads(upload_param) prj_id = common.get_current_project().id importer = ImportService() burst_entity = importer.load_burst_entity(upload_param, prj_id) common.add2session(common.KEY_BURST_CONFIG, burst_entity) except Exception as excep: self.logger.warning(excep.message) common.set_error_message(excep.message) raise cherrypy.HTTPRedirect('/burst/')
def settings(self, save_settings=False, **data): """Main settings page submit and get""" template_specification = dict(mainContent="../settings/system_settings", title="System Settings") if save_settings: try: form = SettingsForm() data = form.to_python(data) isrestart, isreset = self.settingsservice.save_settings(**data) if isrestart: thread = threading.Thread(target=self._restart_services, kwargs={'should_reset': isreset}) thread.start() common.add2session(common.KEY_IS_RESTART, True) common.set_important_message('Please wait until TVB is restarted properly!') raise cherrypy.HTTPRedirect('/tvb') # Here we will leave the same settings page to be displayed. # It will continue reloading when CherryPy restarts. except formencode.Invalid as excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() except InvalidSettingsException as excep: self.logger.error('Invalid settings! Exception %s was raised' % (str(excep))) common.set_error_message(excep.message) template_specification.update({'keys_order': self.settingsservice.KEYS_DISPLAY_ORDER, 'config_data': self.settingsservice.configurable_keys, common.KEY_FIRST_RUN: TvbProfile.is_first_run()}) return self.fill_default_attributes(template_specification)
def save_parameters(self, index_in_tab, **data): """ Save parameters :param tab_nr: the index of the selected tab :param index_in_tab: the index of the configured portlet in the selected tab :param data: the {"portlet_parameters": json_string} Where json_string is a Jsonified dictionary {"name": value}, representing the configuration of the current portlet Having these inputs, current method updated the configuration of the portlet in the corresponding tab position form the burst configuration in session. """ burst_config = common.get_from_session(common.KEY_BURST_CONFIG) tab_nr = burst_config.selected_tab old_portlet_config = burst_config.tabs[int(tab_nr)].portlets[int(index_in_tab)] data = json.loads(data['portlet_parameters']) # Replace all void entries with 'None' for entry in data: if data[entry] == '': data[entry] = None need_relaunch = self.burst_service.update_portlet_configuration(old_portlet_config, data) if need_relaunch: #### Reset Burst Configuration into an entity not persisted (id = None for all) common.add2session(common.KEY_BURST_CONFIG, burst_config.clone()) return "relaunchView" else: self.workflow_service.store_workflow_step(old_portlet_config.visualizer) return "noRelaunch"
def step_1(self, do_reset=0, **kwargs): """ Generate the html for the first step of the local connectivity page. :param do_reset: Boolean telling to start from empty page or not :param kwargs: not actually used, but parameters are still submitted from UI since we just\ use the same js function for this. TODO: do this in a smarter way """ if int(do_reset) == 1: new_context = ContextLocalConnectivity() common.add2session(KEY_LCONN_CONTEXT, new_context) context = common.get_from_session(KEY_LCONN_CONTEXT) right_side_interface = self._get_lconn_interface() left_side_interface = self.get_select_existent_entities('Load Local Connectivity', LocalConnectivity, context.selected_entity) # add interface to session, needed for filters self.add_interface_to_session(left_side_interface, right_side_interface['inputList']) template_specification = dict(title="Surface - Local Connectivity") template_specification['mainContent'] = 'spatial/local_connectivity_step1_main' template_specification.update(right_side_interface) template_specification['displayCreateLocalConnectivityBtn'] = True template_specification['loadExistentEntityUrl'] = LOAD_EXISTING_URL template_specification['resetToDefaultUrl'] = RELOAD_DEFAULT_PAGE_URL template_specification['existentEntitiesInputList'] = left_side_interface template_specification['submit_parameters_url'] = '/spatial/localconnectivity/create_local_connectivity' template_specification['equationViewerUrl'] = '/spatial/localconnectivity/get_equation_chart' template_specification['equationsPrefixes'] = json.dumps(self.plotted_equations_prefixes) template_specification['next_step_url'] = '/spatial/localconnectivity/step_2' msg, msg_type = common.get_message_from_session() template_specification['displayedMessage'] = msg return self.fill_default_attributes(template_specification)
def submit_model_parameters(self, submit_action="cancel_action"): """ Collects the model parameters values from all the models used for the surface vertices. @:param submit_action: a post parameter. It distinguishes if this request is a cancel or a submit """ if submit_action == "submit_action": context_model_parameters = common.get_from_session(KEY_CONTEXT_MPS) burst_configuration = common.get_from_session(common.KEY_BURST_CONFIG) for original_param, modified_param in context_model_parameters.prepared_model_parameter_names.items(): full_name = PARAMS_MODEL_PATTERN % (context_model_parameters.model_name, original_param) param_data = context_model_parameters.get_data_for_model_param(original_param, modified_param) if isinstance(param_data, dict): equation = param_data[KEY_EQUATION] focal_points = param_data[KEY_FOCAL_POINTS] # if focal points or the equation are missing do not update this model parameter if not focal_points or not equation: continue param_data[KEY_EQUATION] = equation.to_json(equation) param_data[KEY_FOCAL_POINTS] = json.dumps(focal_points) param_data = json.dumps(param_data) burst_configuration.update_simulation_parameter(full_name, param_data) ### Update in session BURST configuration for burst-page. common.add2session(common.KEY_BURST_CONFIG, burst_configuration.clone()) ### Clean from session drawing context common.remove_from_session(KEY_CONTEXT_MPS) raise cherrypy.HTTPRedirect("/burst/")
def index(self, **data): """ Login page (with or without messages). """ template_specification = dict(mainContent="login", title="Login", data=data) if cherrypy.request.method == 'POST': form = LoginForm() try: data = form.to_python(data) username = data[KEY_USERNAME] password = data[KEY_PASSWORD] user = self.user_service.check_login(username, password) if user is not None: common.add2session(common.KEY_USER, user) common.set_info_message('Welcome ' + username) self.logger.debug("User " + username + " has just logged in!") if user.selected_project is not None: prj = user.selected_project prj = ProjectService().find_project(prj) self._mark_selected(prj) raise cherrypy.HTTPRedirect('/user/profile') else: common.set_error_message('Wrong username/password, or user not yet validated...') self.logger.debug("Wrong username " + username + " !!!") except formencode.Invalid as excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() return self.fill_default_attributes(template_specification)
def profile(self, logout=False, save=False, **data): """ Display current user's profile page. On POST: logout, or save password/email. """ if cherrypy.request.method == "POST" and logout: raise cherrypy.HTTPRedirect("/user/logout") template_specification = dict(mainContent="profile", title="User Profile") user = common.get_logged_user() if cherrypy.request.method == "POST" and save: try: form = EditUserForm() data = form.to_python(data) if data.get(KEY_PASSWORD): user.password = md5(data[KEY_PASSWORD]).hexdigest() if data.get(KEY_EMAIL): user.email = data[KEY_EMAIL] old_password = None if data.get("old_password"): old_password = md5(data["old_password"]).hexdigest() self.user_service.edit_user(user, old_password) if old_password: common.set_info_message("Changes Submitted!") else: common.set_info_message("Submitted! No password changed.") except formencode.Invalid, excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() except UsernameException, excep: self.logger.exception(excep) user = common.get_logged_user() common.add2session(common.KEY_USER, self.user_service.get_user_by_id(user.id)) common.set_error_message("Could not save changes. Probably wrong old password!!")
def _reset_session_stimuli(self): new_surface_stim = SurfaceStimulusCreatorModel() new_surface_stim.temporal = SurfaceStimulusCreatorForm.default_temporal( ) new_surface_stim.spatial = SurfaceStimulusCreatorForm.default_spatial() self._reset_focal_points(new_surface_stim) common.add2session(KEY_SURFACE_STIMULI, new_surface_stim) common.add2session(KEY_TMP_FORM, EquationTemporalPlotForm())
def reset_burst(self): """ Called when click on "New Burst" entry happens from UI. This will generate an empty new Burst Configuration. """ common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) new_burst = self.burst_service.new_burst_configuration(common.get_current_project().id) common.add2session(common.KEY_BURST_CONFIG, new_burst)
def clean_project_data_from_session(self, remove_project=True): common.remove_from_session(self.KEY_SIMULATOR_CONFIG) common.remove_from_session(self.KEY_LAST_LOADED_FORM_URL) common.remove_from_session(self.KEY_BURST_CONFIG) common.remove_from_session(self.KEY_IS_SIMULATOR_BRANCH) common.add2session(self.KEY_IS_SIMULATOR_LOAD, False) if remove_project: common.remove_project_from_session()
def test_set_model_params(self): self.sess_mock['_tau'] = '[1.0]' self.sess_mock['_I'] = '[0.0]' self.sess_mock['_a'] = '[-2.0]' self.sess_mock['_b'] = '[-10.0]' self.sess_mock['_c'] = '[0.0]' self.sess_mock['_d'] = '[0.02]' self.sess_mock['_e'] = '[3.0]' self.sess_mock['_f'] = '[1.0]' self.sess_mock['_g'] = '[0.0]' self.sess_mock['_alpha'] = '[1.0]' self.sess_mock['_beta'] = '[1.0]' self.sess_mock['_gamma'] = '[1.0]' self.sess_mock['_variables_of_interest'] = 'V' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_model_params(**self.sess_mock._data) assert self.session_stored_simulator.model.tau == [ 1.0 ], "Tau has incorrect value." assert self.session_stored_simulator.model.I == [ 0.0 ], "I has incorrect value." assert self.session_stored_simulator.model.a == [ -2.0 ], "a has incorrect value." assert self.session_stored_simulator.model.b == [ -10.0 ], "b has incorrect value." assert self.session_stored_simulator.model.c == [ 0.0 ], "c has incorrect value." assert self.session_stored_simulator.model.d == [ 0.02 ], "d has incorrect value." assert self.session_stored_simulator.model.e == [ 3.0 ], "e has incorrect value." assert self.session_stored_simulator.model.f == [ 1.0 ], "f has incorrect value." assert self.session_stored_simulator.model.g == [ 0.0 ], "g has incorrect value." assert self.session_stored_simulator.model.alpha == [ 1.0 ], "alpha has incorrect value." assert self.session_stored_simulator.model.beta == [ 1.0 ], "beta has incorrect value." assert self.session_stored_simulator.model.gamma == [ 1.0 ], "gamma has incorrect value." assert self.session_stored_simulator.model.variables_of_interest == ['V'], \ "variables_of_interest has incorrect value."
def index(self): """Get on burst main page""" # todo : reuse load_burst here for consistency. template_specification = dict( mainContent="burst/main_burst", title="Simulation Cockpit", baseUrl=TvbProfile.current.web.BASE_URL, includedResources='project/included_resources') portlets_list = self.burst_service.get_available_portlets() session_stored_burst = common.get_from_session(common.KEY_BURST_CONFIG) if session_stored_burst is None or session_stored_burst.id is None: if session_stored_burst is None: session_stored_burst = self.burst_service.new_burst_configuration( common.get_current_project().id) common.add2session(common.KEY_BURST_CONFIG, session_stored_burst) adapter_interface = self.cached_simulator_input_tree if session_stored_burst is not None: current_data = session_stored_burst.get_all_simulator_values( )[0] adapter_interface = InputTreeManager.fill_defaults( adapter_interface, current_data, True) ### Add simulator tree to session to be available in filters self.context.add_adapter_to_session( self.cached_simulator_algorithm, adapter_interface, current_data) template_specification['inputList'] = adapter_interface selected_portlets = session_stored_burst.update_selected_portlets() template_specification[ 'burst_list'] = self.burst_service.get_available_bursts( common.get_current_project().id) template_specification['portletList'] = portlets_list template_specification['selectedPortlets'] = json.dumps( selected_portlets) template_specification['draw_hidden_ranges'] = True template_specification['burstConfig'] = session_stored_burst ### Prepare PSE available metrics ### We put here all available algorithms, because the metrics select area is a generic one, ### and not loaded with every Burst Group change in history. algorithm = self.flow_service.get_algorithm_by_module_and_class( IntrospectionRegistry.MEASURE_METRICS_MODULE, IntrospectionRegistry.MEASURE_METRICS_CLASS) adapter_instance = ABCAdapter.build_adapter(algorithm) if adapter_instance is not None and hasattr(adapter_instance, 'available_algorithms'): template_specification['available_metrics'] = [ metric_name for metric_name in adapter_instance.available_algorithms ] else: template_specification['available_metrics'] = [] template_specification[common.KEY_PARAMETERS_CONFIG] = False template_specification[common.KEY_SECTION] = 'burst' return self.fill_default_attributes(template_specification)
def set_burst_config(self, burst_config=None): # type: (BurstConfiguration) -> None """ Create a new burst instance only if one does not exist in the context. """ if not burst_config and not self.burst_config: burst_config = BurstConfiguration(self.project.id) if burst_config: common.add2session(self.KEY_BURST_CONFIG, burst_config)
def test_set_integrator(self): self.sess_mock['integrator'] = 'Heun' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_integrator(**self.sess_mock._data) assert isinstance(self.session_stored_simulator.integrator, HeunDeterministic), "Integrator was not set correctly."
def submit(self, node_values): """ Submit noise dispersions :param node_values: A map from state variable names to noise dispersion arrays. Ex {'V': [1,2...74]} """ des = SerializationManager(common.get_from_session(common.KEY_SIMULATOR_CONFIG)) des.write_noise_parameters(json.loads(node_values)) common.add2session(common.KEY_LAST_LOADED_FORM_URL, SimulatorWizzardURLs.SET_NOISE_PARAMS_URL) raise cherrypy.HTTPRedirect("/burst/")
def set_simulator(self, simulator=None): # type: (SimulatorAdapterModel) -> None """ Create a new simulator instance only if one does not exist in the context. """ if not simulator and not self.simulator: simulator = SimulatorAdapterModel() if simulator: common.add2session(self.KEY_SIMULATOR_CONFIG, simulator)
def reset_burst(self): """ Called when click on "New Burst" entry happens from UI. This will generate an empty new Burst Configuration. """ common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) new_burst = self.burst_service.new_burst_configuration( common.get_current_project().id) common.add2session(common.KEY_BURST_CONFIG, new_burst)
def test_set_model(self): self.sess_mock['model'] = 'Generic 2d Oscillator' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_model(**self.sess_mock._data) assert isinstance(self.session_stored_simulator.model, ModelsEnum.GENERIC_2D_OSCILLATOR.get_class()), "Model class is incorrect."
def copy_burst(self, burst_id): """ When currently selected entry is a valid Burst, create a clone of that Burst. """ common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) base_burst = self.burst_service.load_burst(burst_id)[0] if (base_burst is None) or (base_burst.id is None): return self.reset_burst() common.add2session(common.KEY_BURST_CONFIG, base_burst.clone()) return base_burst.name
def test_set_monitors(self): self.sess_mock['_monitor'] = 'Temporal average' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_monitors(**self.sess_mock._data) assert isinstance(self.session_stored_simulator.monitors[0], TemporalAverage), 'Monitor class is incorrect.'
def test_set_integrator_params(self): self.sess_mock['_dt'] = '0.01220703125' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_integrator_params( **self.sess_mock._data) assert self.session_stored_simulator.integrator.dt == 0.01220703125, 'dt value was not set correctly.'
def test_set_coupling_params(self): self.sess_mock['a'] = '[0.00390625]' self.sess_mock['b'] = '[0.0]' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_coupling_params(**self.sess_mock._data) assert self.session_stored_simulator.coupling.a[0] == [0.00390625], "a value was not set correctly." assert self.session_stored_simulator.coupling.b[0] == [0.0], "b value was not set correctly."
def test_launch_simulation_with_default_parameters(self): self.sess_mock['input-simulation-name-id'] = 'HappySimulation' launch_mode = 'new' burst_config = BurstConfiguration(self.test_project.id) with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_BURST_CONFIG, burst_config) common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.launch_simulation(launch_mode, **self.sess_mock._data)
def test_load_burst_only(self): zip_path = path.join(path.dirname(tvb_data.__file__), 'connectivity', 'connectivity_66.zip') TestFactory.import_zip_connectivity(self.test_user, self.test_project, zip_path, "John") connectivity = TestFactory.get_entity(self.test_project, ConnectivityIndex) simulator_index = SimulatorIndex() simulator_index.fill_from_has_traits(self.session_stored_simulator) burst_config = BurstConfiguration(self.test_project.id, simulator_index.id) burst_config = dao.store_entity(burst_config) simulator_index.fk_from_operation = burst_config.id simulator_index = dao.store_entity(simulator_index) simulator_index.fk_parent_burst = burst_config.id simulator_index = dao.store_entity(simulator_index) burst = dao.get_bursts_for_project(self.test_project.id) self.sess_mock['burst_id'] = str(burst[0].id) self.sess_mock['_connectivity'] = connectivity.gid self.sess_mock['_conduction_speed'] = "3.0" self.sess_mock['_coupling'] = "Sigmoidal" with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_connectivity(**self.sess_mock._data) self.simulator_controller.set_stimulus(**self.sess_mock._data) storage_path = FilesHelper().get_project_folder( self.test_project, str(simulator_index.fk_from_operation)) simulator_service = SimulatorService() SimulatorSerializer().serialize_simulator( self.session_stored_simulator, simulator_index.gid, None, storage_path) with patch('cherrypy.session', self.sess_mock, create=True): self.simulator_controller.load_burst_read_only(str(burst[0].id)) is_simulator_load = common.get_from_session(KEY_IS_SIMULATOR_LOAD) is_simulator_copy = common.get_from_session(KEY_IS_SIMULATOR_COPY) last_loaded_form_url = common.get_from_session( KEY_LAST_LOADED_FORM_URL) database_simulator = dao.get_generic_entity(SimulatorIndex, burst_config.id, 'fk_parent_burst')[0] assert simulator_index.gid == database_simulator.gid, "Simulator was not added correctly!" assert is_simulator_load, "Simulator Load Flag should be True!" assert not is_simulator_copy, "Simulator Copy Flag should be False!" assert last_loaded_form_url == '/burst/setup_pse', "Incorrect last form URL!"
def test_set_monitors(self): self.sess_mock['monitors'] = ['Temporal average'] self.session_stored_simulator.monitors[0].variables_of_interest = numpy.array([0]) self.session_stored_simulator.model.variables_of_interest = ['V', 'W'] with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) common.add2session(common.KEY_BURST_CONFIG, BurstConfiguration(self.test_project.id)) self.simulator_controller.set_monitors(**self.sess_mock._data) assert isinstance(self.session_stored_simulator.monitors[0], TemporalAverage), 'Monitor class is incorrect.'
def test_set_simulation_length_with_burst_config_name(self): burst_config = BurstConfiguration(self.test_project.id) burst_config.name = "Test Burst Config" self.sess_mock['simulation_length'] = '1000.0' with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) common.add2session(common.KEY_BURST_CONFIG, burst_config) self.simulator_controller.set_simulation_length(**self.sess_mock._data) assert self.session_stored_simulator.simulation_length == 1000.0, "simulation_length was not set correctly."
def test_set_temporal_average_monitor_params(self): with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_monitor_params( **self.sess_mock._data) assert self.session_stored_simulator.monitors[ 0].period == 0.9765625, "period should be set to default value." assert self.session_stored_simulator.monitors[0].variables_of_interest is None, \ "Default for variables_of_interest is None"
def test_set_seeg_monitor_params(self): region_mapping = self.set_region_mapping() seeg_sensors_file = path.join(path.dirname(tvb_data.sensors.__file__), 'seeg_588.txt') seeg_sensors = TestFactory.import_sensors( self.test_user, self.test_project, seeg_sensors_file, SensorsImporterModel.OPTIONS['Internal Sensors']) surface_file = path.join(path.dirname(tvb_data.surfaceData.__file__), 'cortex_16384.zip') surface = TestFactory.import_surface_zip(self.test_user, self.test_project, surface_file, CORTICAL, True) seeg_projection_file = path.join( path.dirname(tvb_data.projectionMatrix.__file__), 'projection_seeg_588_surface_16k.npy') seeg_projections = TestFactory.import_projection_matrix( self.test_user, self.test_project, seeg_projection_file, seeg_sensors.gid, surface.gid) self.session_stored_simulator.model.variables_of_interest = ('V', 'W', 'V - W') variable_of_interest_indexes = {'W': 1, 'V - W': 2} self.sess_mock['variables_of_interest'] = list( variable_of_interest_indexes.keys()) self.sess_mock['period'] = '0.75' self.sess_mock['region_mapping'] = region_mapping.gid self.sess_mock['projection'] = seeg_projections.gid self.sess_mock['sigma'] = "1.0" self.sess_mock['sensors'] = seeg_sensors.gid self.session_stored_simulator.monitors = [iEEG()] with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) common.add2session(common.KEY_BURST_CONFIG, BurstConfiguration(self.test_project.id)) self.simulator_controller.set_monitor_params( 'iEEG', **self.sess_mock._data) assert self.session_stored_simulator.monitors[ 0].period == 0.75, "Period was not set correctly." assert list(self.session_stored_simulator.monitors[0].variables_of_interest) == \ list(variable_of_interest_indexes.values()), "Variables of interest were not set correctly." assert self.session_stored_simulator.monitors[0].region_mapping.gid.hex == region_mapping.gid, \ "Region Mapping wasn't set and stored correctly." assert self.session_stored_simulator.monitors[0].sensors.gid.hex == seeg_sensors.gid, \ "Region Mapping wasn't set and stored correctly." assert self.session_stored_simulator.monitors[0].projection.gid is not None, \ "Projection wasn't stored correctly."
def test_set_surface(self): zip_path = path.join(path.dirname(tvb_data.surfaceData.__file__), 'cortex_16384.zip') TestFactory.import_surface_zip(self.test_user, self.test_project, zip_path, CORTICAL, True) surface = TestFactory.get_entity(self.test_project, SurfaceIndex) self.sess_mock['surface'] = surface.gid with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_surface(**self.sess_mock._data) assert self.session_stored_simulator.surface is not None, "Surface was not set."
def cached_simulator_input_tree(self): """ Cache Simulator's input tree, for performance issues. Anyway, without restart, the introspected tree will not be different on multiple executions. :returns: Simulator's Input Tree (copy from cache or just loaded) """ cached_simulator_tree = common.get_from_session(common.KEY_CACHED_SIMULATOR_TREE) if cached_simulator_tree is None: cached_simulator_tree = self.flow_service.prepare_adapter(common.get_current_project().id, self.cached_simulator_algorithm) common.add2session(common.KEY_CACHED_SIMULATOR_TREE, cached_simulator_tree) return copy.deepcopy(cached_simulator_tree)
def index(self, **data): """ Login page (with or without messages). """ template_specification = dict(mainContent="user/login", title="Login", data=data) self._set_base_url() if cherrypy.request.method == 'POST': keycloak_login = TvbProfile.current.KEYCLOAK_LOGIN_ENABLED form = LoginForm() if not keycloak_login else KeycloakLoginForm() try: data = form.to_python(data) if keycloak_login: auth_token = data[KEY_AUTH_TOKEN] kc_user_info = AuthorizationManager( TvbProfile.current.KEYCLOAK_WEB_CONFIG ).get_keycloak_instance().userinfo(auth_token) user = self.user_service.get_external_db_user(kc_user_info) else: username = data[KEY_USERNAME] password = data[KEY_PASSWORD] user = self.user_service.check_login(username, password) if user is not None: common.add2session(common.KEY_USER, user) common.set_info_message('Welcome ' + user.display_name) self.logger.debug("User " + user.username + " has just logged in!") if user.selected_project is not None: prj = user.selected_project prj = ProjectService().find_project(prj) self._mark_selected(prj) raise cherrypy.HTTPRedirect('/user/profile') elif not keycloak_login: common.set_error_message( 'Wrong username/password, or user not yet validated...' ) self.logger.debug("Wrong username " + username + " !!!") else: common.set_error_message( 'Your account is not validated. Please contact us at [email protected] for more details' ) self.logger.debug("Invalidated account") template_specification[common.KEY_ERRORS] = { 'invalid_user': True } except formencode.Invalid as excep: template_specification[ common.KEY_ERRORS] = excep.unpack_errors() return self.fill_default_attributes(template_specification)
def view_stimulus(self, focal_points): """ Just create the stimulus to view the actual data, don't store to db. Hold the entity in session without the surface, so the next time you need data just get from that one. """ try: context = common.get_from_session(KEY_SURFACE_CONTEXT) context.set_focal_points(focal_points) kwargs = copy.deepcopy(context.equation_kwargs) surface_stimulus_creator = self.get_creator_and_interface( SURFACE_STIMULUS_CREATOR_MODULE, SURFACE_STIMULUS_CREATOR_CLASS, StimuliSurface())[0] min_time = float(kwargs.get('min_tmp_x', 0)) max_time = float(kwargs.get('max_tmp_x', 100)) kwargs = surface_stimulus_creator.prepare_ui_inputs(kwargs) stimulus = surface_stimulus_creator.launch(**kwargs) surface_gid = common.get_from_session(PARAM_SURFACE) surface = ABCAdapter.load_entity_by_gid(surface_gid) stimulus.surface = surface stimulus.configure_space() time = numpy.arange(min_time, max_time, 1) time = time[numpy.newaxis, :] stimulus.configure_time(time) data = [] max_value = numpy.max(stimulus()) min_value = numpy.min(stimulus()) for i in range(min(CHUNK_SIZE, stimulus.temporal_pattern.shape[1])): step_data = stimulus(i).tolist() data.append(step_data) stimulus.surface = surface.gid common.add2session(KEY_STIMULUS, stimulus) result = { 'status': 'ok', 'max': max_value, 'min': min_value, 'data': data, "time_min": min_time, "time_max": max_time, "chunk_size": CHUNK_SIZE } return result except (NameError, ValueError, SyntaxError): return { 'status': 'error', 'errorMsg': "Could not generate stimulus data. Some of the parameters hold invalid characters." } except Exception, ex: return {'allSeries': 'error', 'errorMsg': ex.message}
def update_operations_count(self): """ If a project is selected, update Operation Numbers in call-out. """ project = common.get_current_project() if project is not None: fns, sta, err, canceled, pending = self.algorithm_service.get_operation_numbers(project.id) project.operations_finished = fns project.operations_started = sta project.operations_error = err project.operations_canceled = canceled project.operations_pending = pending common.add2session(common.KEY_PROJECT, project)
def step_1_submit(self, next_step, do_reset=0, **kwargs): """ Any submit from the first step should be handled here. Update the context then go to the next step as required. In case a reset is needed create a clear context. """ if int(do_reset) == 1: new_context = RegionStimulusContext() common.add2session(KEY_REGION_CONTEXT, new_context) context = common.get_from_session(KEY_REGION_CONTEXT) if kwargs.get(CONNECTIVITY_PARAMETER) != context.get_session_connectivity(): context.set_weights([]) context.equation_kwargs = kwargs return self.do_step(next_step)
def step_1_submit(self, next_step, do_reset=0, **kwargs): """ Any submit from the first step should be handled here. Update the context then go to the next step as required. In case a reset is needed create a clear context. """ if int(do_reset) == 1: new_context = SurfaceStimulusContext() common.add2session(KEY_SURFACE_CONTEXT, new_context) context = common.get_from_session(KEY_SURFACE_CONTEXT) if kwargs.get(SURFACE_PARAMETER) != context.get_session_surface(): context.set_focal_points('[]') context.update_eq_kwargs(kwargs) return self.do_step(next_step)
def test_set_monitor_params(self): self.sess_mock['period'] = '0.8' self.sess_mock['variables_of_interest'] = 'anything' self.session_stored_simulator.monitors = [SubSample()] with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_SIMULATOR_CONFIG, self.session_stored_simulator) self.simulator_controller.set_monitor_params(**self.sess_mock._data) assert self.session_stored_simulator.monitors[0].period == 0.8, "Period was not set correctly." assert self.session_stored_simulator.monitors[0].variables_of_interest is None, \ "Variables of interest should be None."
def step_1(self, do_reset=0, **kwargs): """ Generate the html for the first step of the local connectivity page. :param do_reset: Boolean telling to start from empty page or not :param kwargs: not actually used, but parameters are still submitted from UI since we just\ use the same js function for this. """ project_id = common.get_current_project().id if int(do_reset) == 1: new_lconn = LocalConnectivityCreatorModel() default_surface_index = try_get_last_datatype(project_id, SurfaceIndex, LocalConnectivityCreatorForm.get_filters()) if default_surface_index: new_lconn.surface = uuid.UUID(default_surface_index.gid) else: # Surface is required in model and we should keep it like this, but we also want to new_lconn.surface = uuid.uuid4() common.set_error_message(self.MSG_MISSING_SURFACE) common.add2session(KEY_LCONN, new_lconn) current_lconn = common.get_from_session(KEY_LCONN) existent_lcon_form = self.algorithm_service.prepare_adapter_form(form_instance=LocalConnectivitySelectorForm(), project_id=common.get_current_project().id) existent_lcon_form.existentEntitiesSelect.data = current_lconn.gid.hex configure_lcon_form = self.algorithm_service.prepare_adapter_form( form_instance=LocalConnectivityCreatorForm(), project_id=common.get_current_project().id) configure_lcon_form.fill_from_trait(current_lconn) current_lconn.equation = configure_lcon_form.spatial.value() template_specification = dict(title="Surface - Local Connectivity") template_specification['mainContent'] = 'spatial/local_connectivity_step1_main' template_specification['inputList'] = self.render_spatial_form(configure_lcon_form) template_specification['displayCreateLocalConnectivityBtn'] = True template_specification['loadExistentEntityUrl'] = LOAD_EXISTING_URL template_specification['resetToDefaultUrl'] = RELOAD_DEFAULT_PAGE_URL template_specification['existentEntitiesInputList'] = self.render_spatial_form(existent_lcon_form) template_specification['submit_parameters_url'] = '/spatial/localconnectivity/create_local_connectivity' template_specification['equationViewerUrl'] = '/spatial/localconnectivity/get_equation_chart' template_specification['baseUrl'] = self.base_url self.plotted_equation_prefixes = {self.SURFACE_FIELD: configure_lcon_form.surface.name, self.EQUATION_FIELD: configure_lcon_form.spatial.name, self.CUTOFF_FIELD: configure_lcon_form.cutoff.name, self.DISPLAY_NAME_FIELD: configure_lcon_form.display_name.name, self.EQUATION_PARAMS_FIELD: configure_lcon_form.spatial.subform_field.name[1:]} template_specification['equationsPrefixes'] = json.dumps(self.plotted_equation_prefixes) template_specification['next_step_url'] = '/spatial/localconnectivity/step_2' return self.fill_default_attributes(template_specification)
def __get_operations_filters(self): """ Filters for VIEW_ALL_OPERATIONS page. Get from session currently selected filters, or build a new set of filters. """ session_filtes = common.get_from_session(self.KEY_OPERATION_FILTERS) if session_filtes: return session_filtes else: sim_group = self.flow_service.get_algorithm_by_module_and_class(SIMULATOR_MODULE, SIMULATOR_CLASS)[1] new_filters = StaticFiltersFactory.build_operations_filters(sim_group, common.get_logged_user().id) common.add2session(self.KEY_OPERATION_FILTERS, new_filters) return new_filters
def step_1_submit(self, next_step, do_reset=0, **kwargs): """ Any submit from the first step should be handled here. Update the context then go to the next step as required. In case a reset is needed create a clear context. """ if int(do_reset) == 1: new_context = RegionStimulusContext() common.add2session(KEY_REGION_CONTEXT, new_context) context = common.get_from_session(KEY_REGION_CONTEXT) if kwargs.get( CONNECTIVITY_PARAMETER) != context.get_session_connectivity(): context.set_weights([]) context.equation_kwargs = kwargs return self.do_step(next_step)
def test_load_burst_history(self): burst_config1 = BurstConfiguration(self.test_project.id) burst_config2 = BurstConfiguration(self.test_project.id) burst_config3 = BurstConfiguration(self.test_project.id) dao.store_entity(burst_config1) dao.store_entity(burst_config2) dao.store_entity(burst_config3) with patch('cherrypy.session', self.sess_mock, create=True): common.add2session(common.KEY_BURST_CONFIG, burst_config1) burst_parameters = self.simulator_controller.load_burst_history() assert len(burst_parameters['burst_list']) == 3, "The burst configurations where not stored."
def reload_burst_operation(self, operation_id, is_group, **_): """ Find out from which burst was this operation launched. Set that burst as the selected one and redirect to the burst page. """ is_group = int(is_group) if not is_group: operation = self.flow_service.load_operation(int(operation_id)) else: op_group = ProjectService.get_operation_group_by_id(operation_id) first_op = ProjectService.get_operations_in_group(op_group)[0] operation = self.flow_service.load_operation(int(first_op.id)) operation.burst.prepare_after_load() common.add2session(common.KEY_BURST_CONFIG, operation.burst) raise cherrypy.HTTPRedirect("/burst/")
def apply_equation(self, **kwargs): """ Applies an equations for computing a model parameter. """ submitted_data = collapse_params(kwargs, ['model_param']) model_param, equation = self._compute_equation(submitted_data) context_model_parameters = common.get_from_session(KEY_CONTEXT_MPS) context_model_parameters.apply_equation(model_param, equation) common.add2session(KEY_CONTEXT_MPS, context_model_parameters) template_specification = self.get_surface_model_parameters_data(model_param) template_specification = self._add_entra_equation_entries(template_specification, kwargs['min_x'], kwargs['max_x']) template_specification['equationViewerUrl'] = '/spatial/modelparameters/surface/get_equation_chart' template_specification['equationsPrefixes'] = json.dumps(self.plotted_equations_prefixes) return self.fill_default_attributes(template_specification)
def get_visualizers_for_operation_id(self, op_id, width, height): """ Method called from parameters exploration page in case a burst with a range of parameters for the simulator was launched. :param op_id: the selected operation id from the parameter space exploration. :param width: the width of the right side display :param height: the height of the right side display Given these parameters first get the workflow to which op_id belongs, then load the portlets from that workflow as the current burst configuration. Width and height are used to get the proper sizes for the visualization iFrames. """ burst_config = common.get_from_session(common.KEY_BURST_CONFIG) burst_config = self.burst_service.load_tab_configuration(burst_config, op_id) common.add2session(common.KEY_BURST_CONFIG, burst_config) return self.load_configured_visualizers(width, height)
def update_operations_count(self): """ If a project is selected, update Operation Numbers in call-out. """ project = common.get_current_project() if project is not None: fns, sta, err, canceled, pending = self.flow_service.get_operation_numbers(project.id) project.operations_finished = fns project.operations_started = sta project.operations_error = err project.operations_canceled = canceled project.operations_pending = pending common.add2session(common.KEY_PROJECT, project)
def display_surface(surface_gid): """ Generates the HTML for displaying the surface with the given ID. """ surface = ABCAdapter.load_entity_by_gid(surface_gid) common.add2session(PARAM_SURFACE, surface_gid) url_vertices_pick, url_normals_pick, url_triangles_pick = surface.get_urls_for_pick_rendering() url_vertices, url_normals, _, url_triangles = surface.get_urls_for_rendering() return { 'urlVerticesPick': json.dumps(url_vertices_pick), 'urlTrianglesPick': json.dumps(url_triangles_pick), 'urlNormalsPick': json.dumps(url_normals_pick), 'urlVertices': json.dumps(url_vertices), 'urlTriangles': json.dumps(url_triangles), 'urlNormals': json.dumps(url_normals), 'brainCenter': json.dumps(surface.center()) }
def index(self): """Get on burst main page""" # todo : reuse load_burst here for consistency. template_specification = dict(mainContent="burst/main_burst", title="Simulation Cockpit", baseUrl=TvbProfile.current.web.BASE_URL, includedResources='project/included_resources') portlets_list = self.burst_service.get_available_portlets() session_stored_burst = common.get_from_session(common.KEY_BURST_CONFIG) if session_stored_burst is None or session_stored_burst.id is None: if session_stored_burst is None: session_stored_burst = self.burst_service.new_burst_configuration(common.get_current_project().id) common.add2session(common.KEY_BURST_CONFIG, session_stored_burst) adapter_interface = self.cached_simulator_input_tree if session_stored_burst is not None: current_data = session_stored_burst.get_all_simulator_values()[0] adapter_interface = ABCAdapter.fill_defaults(adapter_interface, current_data, True) ### Add simulator tree to session to be available in filters self.context.add_adapter_to_session(self.cached_simulator_algo_group, adapter_interface, current_data) template_specification['inputList'] = adapter_interface selected_portlets = session_stored_burst.update_selected_portlets() template_specification['burst_list'] = self.burst_service.get_available_bursts(common.get_current_project().id) template_specification['portletList'] = portlets_list template_specification['selectedPortlets'] = json.dumps(selected_portlets) template_specification['draw_hidden_ranges'] = True template_specification['burstConfig'] = session_stored_burst ### Prepare PSE available metrics ### We put here all available algorithms, because the metrics select area is a generic one, ### and not loaded with every Burst Group change in history. algo_group = self.flow_service.get_algorithm_by_module_and_class(MEASURE_METRICS_MODULE, MEASURE_METRICS_CLASS)[1] adapter_instance = ABCAdapter.build_adapter(algo_group) if adapter_instance is not None and hasattr(adapter_instance, 'available_algorithms'): template_specification['available_metrics'] = [metric_name for metric_name in adapter_instance.available_algorithms.keys()] else: template_specification['available_metrics'] = [] template_specification[common.KEY_PARAMETERS_CONFIG] = False template_specification[common.KEY_SECTION] = 'burst' return self.fill_default_attributes(template_specification)
def profile(self, logout=False, save=False, **data): """ Display current user's profile page. On POST: logout, or save password/email. """ if cherrypy.request.method == 'POST' and logout: raise cherrypy.HTTPRedirect('/user/logout') template_specification = dict(mainContent="profile", title="User Profile") user = common.get_logged_user() if cherrypy.request.method == 'POST' and save: try: form = EditUserForm() data = form.to_python(data) if data.get(KEY_PASSWORD): user.password = md5(data[KEY_PASSWORD]).hexdigest() if data.get(KEY_EMAIL): user.email = data[KEY_EMAIL] old_password = None if data.get('old_password'): old_password = md5(data['old_password']).hexdigest() self.user_service.edit_user(user, old_password) if old_password: common.set_info_message("Changes Submitted!") else: common.set_info_message("Submitted! No password changed.") except formencode.Invalid as excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() except UsernameException as excep: self.logger.exception(excep) user = common.get_logged_user() common.add2session(common.KEY_USER, self.user_service.get_user_by_id(user.id)) common.set_error_message("Could not save changes. Probably wrong old password!!") else: #Update session user since disk size might have changed from last time to profile. user = self.user_service.get_user_by_id(user.id) common.add2session(common.KEY_USER, user) template_specification['user_used_disk_human'] = format_bytes_human( self.user_service.compute_user_generated_disk_size(user.id)) return self.fill_default_attributes(template_specification)
def _mark_selected(self, project): """ Set the project passed as parameter as the selected project. """ previous_project = common.get_current_project() ### Update project stored in selection, with latest Project entity from DB. members = self.user_service.get_users_for_project("", project.id)[1] project.members = members common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) common.add2session(common.KEY_PROJECT, project) if previous_project is None or previous_project.id != project.id: ### Clean Burst selection from session in case of a different project. common.remove_from_session(common.KEY_BURST_CONFIG) ### Store in DB new project selection user = common.get_from_session(common.KEY_USER) if user is not None: self.user_service.save_project_to_user(user.id, project.id) ### Display info message about project change self.logger.debug("Selected project is now " + project.name) common.set_info_message("Your current working project is: " + str(project.name))
def edit_model_parameters(self): """ Main method, to initialize Model-Parameter visual-set. """ model, surface = self.get_data_from_burst_configuration() context_model_parameters = SurfaceContextModelParameters(surface, model) common.add2session(KEY_CONTEXT_MPS, context_model_parameters) template_specification = dict(title="Spatio temporal - Model parameters") template_specification.update(self.display_surface(surface.gid)) model_params_data = self.get_surface_model_parameters_data() model_params_data = self._add_entra_equation_entries(model_params_data) template_specification.update(model_params_data) template_specification.update( submit_parameters_url='/spatial/modelparameters/surface/submit_model_parameters', mainContent='spatial/model_param_surface_main', equationViewerUrl='/spatial/modelparameters/surface/get_equation_chart', equationsPrefixes=json.dumps(self.plotted_equations_prefixes), submitSurfaceParametersBtn=True ) return self.fill_default_attributes(template_specification)
def settings(self, save_settings=False, **data): """Main settings page submit and get""" template_specification = dict(mainContent="../settings/system_settings", title="System Settings") if save_settings: try: form = SettingsForm() data = form.to_python(data) isrestart, isreset = self.settingsservice.save_settings(**data) if isrestart: thread = threading.Thread(target=self._restart_services, kwargs={'should_reset': isreset}) thread.start() common.add2session(common.KEY_IS_RESTART, True) common.set_important_message('Please wait until TVB is restarted properly!') raise cherrypy.HTTPRedirect('/tvb') # Here we will leave the same settings page to be displayed. # It will continue reloading when CherryPy restarts. except formencode.Invalid, excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() except InvalidSettingsException, excep: self.logger.error('Invalid settings! Exception %s was raised' % (str(excep))) common.set_error_message(excep.message)
def view_stimulus(self, focal_points): """ Just create the stimulus to view the actual data, don't store to db. Hold the entity in session without the surface, so the next time you need data just get from that one. """ try: context = common.get_from_session(KEY_SURFACE_CONTEXT) context.set_focal_points(focal_points) kwargs = copy.deepcopy(context.equation_kwargs) surface_stimulus_creator = self.get_creator_and_interface(SURFACE_STIMULUS_CREATOR_MODULE, SURFACE_STIMULUS_CREATOR_CLASS, StimuliSurface())[0] min_time = float(kwargs.get('min_tmp_x', 0)) max_time = float(kwargs.get('max_tmp_x', 100)) kwargs = surface_stimulus_creator.prepare_ui_inputs(kwargs) stimulus = surface_stimulus_creator.launch(**kwargs) surface_gid = common.get_from_session(PARAM_SURFACE) surface = ABCAdapter.load_entity_by_gid(surface_gid) stimulus.surface = surface stimulus.configure_space() time = numpy.arange(min_time, max_time, 1) time = time[numpy.newaxis, :] stimulus.configure_time(time) data = [] max_value = numpy.max(stimulus()) min_value = numpy.min(stimulus()) for i in range(min(CHUNK_SIZE, stimulus.temporal_pattern.shape[1])): step_data = stimulus(i).tolist() data.append(step_data) stimulus.surface = surface.gid common.add2session(KEY_STIMULUS, stimulus) result = {'status': 'ok', 'max': max_value, 'min': min_value, 'data': data, "time_min": min_time, "time_max": max_time, "chunk_size": CHUNK_SIZE} return result except (NameError, ValueError, SyntaxError): return {'status': 'error', 'errorMsg': "Could not generate stimulus data. Some of the parameters hold invalid characters."} except Exception, ex: return {'allSeries': 'error', 'errorMsg': ex.message}
def add_adapter_to_session(self, algo_group, input_tree, default_data=None): """ Put in session information about currently selected adapter. Will be used by filters and efficiency load. """ previous_algo = self.get_current_substep() current_algo = algo_group.id if algo_group is not None else (default_data[common.KEY_ADAPTER] if default_data is not None else None) if current_algo is None or str(current_algo) != str(previous_algo): self.clean_from_session() adapter_info = {} else: adapter_info = common.get_from_session(self.KEY_CURRENT_ADAPTER_INFO) if default_data is not None: adapter_info[self._KEY_SELECTED_DATA] = default_data if input_tree is not None: adapter_info[self._KEY_INPUT_TREE] = input_tree if algo_group is not None: adapter_info[self._KEY_CURRENT_STEP] = algo_group.fk_category adapter_info[self._KEY_CURRENT_SUBSTEP] = algo_group.id common.add2session(self.KEY_CURRENT_ADAPTER_INFO, adapter_info)
def load_burst(self, burst_id): """ Given a burst id return its running status, weather it was a operation group and the selected tab. This is called when a burst is selected in the history, when returning from a burst config page (model param or noise) and when the status of running simulations is polled. Besides returning these values it updates the session stored burst. A burst configuration has 2 meanings. It is a staging configuration for a new burst (stored in transients in the session). It is the configuration used to launch a simulation and it's running status (stored in the db). This method has to merge the two meanings. If the requested burst_id is different from the one held in the session, then the burst config is loaded from the db, discarding any session stored config. If the id is the same then the session config is kept. """ try: burst_id = int(burst_id) old_burst = common.get_from_session(common.KEY_BURST_CONFIG) burst, group_gid = self.burst_service.load_burst(burst_id) if old_burst and old_burst.id == burst_id: # This function was called to reload the current burst. # Merge session config into the db config. Overwrite all transient fields burst.simulator_configuration = old_burst.simulator_configuration burst.dynamic_ids = old_burst.dynamic_ids burst.selected_tab = old_burst.selected_tab common.add2session(common.KEY_BURST_CONFIG, burst) return {'status': burst.status, 'group_gid': group_gid, 'selected_tab': burst.selected_tab} except Exception: ### Most probably Burst was removed. Delete it from session, so that client ### has a good chance to get a good response on refresh self.logger.exception("Error loading burst") common.remove_from_session(common.KEY_BURST_CONFIG) raise
def mark_file_for_delete(file_name, delete_parent_folder=False): """ This method stores provided file name in session, and later on when request is done, all these files/folders are deleted :param file_name: name of the file or folder to be deleted :param delete_parent_folder: specify if the parent folder of the file should be removed too. """ # No processing if no file specified if file_name is None: return files_list = common.get_from_session(FILES_TO_DELETE_ATTR) if files_list is None: files_list = [] common.add2session(FILES_TO_DELETE_ATTR, files_list) # Now add file/folder to list if delete_parent_folder: folder_name = os.path.split(file_name)[0] files_list.append(folder_name) else: files_list.append(file_name)
def _cache(self): cache = common.get_from_session(self.SESSION_KEY) if cache is None: cache = {} common.add2session(self.SESSION_KEY, cache) return cache
self.user_service.edit_user(user, old_password) if old_password: common.set_info_message("Changes Submitted!") else: common.set_info_message("Submitted! No password changed.") except formencode.Invalid, excep: template_specification[common.KEY_ERRORS] = excep.unpack_errors() except UsernameException, excep: self.logger.exception(excep) user = common.get_logged_user() common.add2session(common.KEY_USER, self.user_service.get_user_by_id(user.id)) common.set_error_message("Could not save changes. Probably wrong old password!!") else: # Update session user since disk size might have changed from last time to profile. user = self.user_service.get_user_by_id(user.id) common.add2session(common.KEY_USER, user) template_specification["user_used_disk_human"] = format_bytes_human( self.user_service.compute_user_generated_disk_size(user.id) ) return self.fill_default_attributes(template_specification) @cherrypy.expose @handle_error(redirect=True) @check_user def logout(self): """ Logging out user and clean session """ user = common.remove_from_session(common.KEY_USER) if user is not None: