Source code for tvb.interfaces.web.controllers.project.figure_controller

# -*- coding: utf-8 -*-
#
#
# TheVirtualBrain-Framework Package. This package holds all Data Management, and 
# Web-UI helpful to run brain-simulations. To use it, you also need to download
# TheVirtualBrain-Scientific Package (for simulators). See content of the
# documentation-folder for more details. See also http://www.thevirtualbrain.org
#
# (c) 2012-2023, Baycrest Centre for Geriatric Care ("Baycrest") and others
#
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this
# program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#   CITATION:
# When using The Virtual Brain for scientific publications, please cite it as explained here:
# https://www.thevirtualbrain.org/tvb/zwei/neuroscience-publications
#
#

"""
Controller class for managing Figures saved in TVB.

.. moduleauthor:: Ciprian Tomoiaga <ciprian.tomoiaga@codemart.ro>
.. moduleauthor:: Lia Domide <lia.domide@codemart.ro>
"""

import os
import cherrypy
import formencode
from formencode import validators
from cherrypy.lib.static import serve_file
from tvb.core import utils
from tvb.core.services.figure_service import FigureService
from tvb.interfaces.web.controllers import common
from tvb.interfaces.web.controllers.autologging import traced
from tvb.interfaces.web.controllers.decorators import context_selected, check_user, handle_error
from tvb.interfaces.web.controllers.decorators import using_template, expose_page
from tvb.interfaces.web.controllers.project.project_controller import ProjectController
from tvb.storage.storage_interface import StorageInterface


[docs]@traced class FigureController(ProjectController): """ Resulting Figures are user-saved figures with specific visualizers or TVB pages which are considered important. """ def __init__(self): ProjectController.__init__(self) self.storage_interface = StorageInterface() self.figure_service = FigureService()
[docs] @cherrypy.expose @handle_error(redirect=False) @check_user @context_selected def storeresultfigure(self, img_type, **kwargs): """Create preview for current displayed canvas and store image in current session, for future comparison.""" project = common.get_current_project() user = common.get_logged_user() suggested_name = kwargs.get("suggestedName") self.figure_service.store_result_figure(project, user, img_type, kwargs['export_data'], suggested_name)
[docs] @expose_page @context_selected def displayresultfigures(self, selected_session='all_sessions'): """ Collect and display saved previews, grouped by session.""" project = common.get_current_project() user = common.get_logged_user() data, all_sessions_info = self.figure_service.retrieve_result_figures(project, user, selected_session) manage_figure_title = "Figures for " + str(selected_session) + " category" if selected_session == 'all_sessions': manage_figure_title = "Figures for all categories" template_specification = dict(mainContent="project/figures_display", title="Stored Visualizer Previews", controlPage=None, displayControl=False, selected_sessions_data=data, all_sessions_info=all_sessions_info, selected_session=selected_session, manageFigureTitle=manage_figure_title) template_specification = self.fill_default_attributes(template_specification, subsection='figures') return template_specification
[docs] @cherrypy.expose @handle_error(redirect=True) @check_user @context_selected def editresultfigures(self, remove_figure=False, rename_session=False, remove_session=False, **data): """ This method knows how to handle the following actions: remove figure, update figure, remove session and update session. """ project = common.get_current_project() user = common.get_logged_user() redirect_url = '/project/figure/displayresultfigures' if "selected_session" in data and data["selected_session"] is not None and len(data["selected_session"]): redirect_url += '/' + data["selected_session"] del data["selected_session"] figure_id = None if "figure_id" in data: figure_id = data["figure_id"] del data["figure_id"] if cherrypy.request.method == 'POST' and rename_session: successfully_updated = True if "old_session_name" in data and "new_session_name" in data: figures_dict, _ = self.figure_service.retrieve_result_figures(project, user, data["old_session_name"]) for _key, value in figures_dict.items(): for figure in value: new_data = {"name": figure.name, "session_name": data["new_session_name"]} success = self._update_figure(figure.id, **new_data) if not success: successfully_updated = False if successfully_updated: common.set_info_message("The session was successfully updated!") else: common.set_error_message("The session was not successfully updated! " "There could be some figures that still refer to the old session.") elif cherrypy.request.method == 'POST' and remove_session: successfully_removed = True if "old_session_name" in data: figures_dict, _ = self.figure_service.retrieve_result_figures(project, user, data["old_session_name"]) for _key, value in figures_dict.items(): for figure in value: success = self.figure_service.remove_result_figure(figure.id) if not success: successfully_removed = False if successfully_removed: common.set_info_message("The session was removed successfully!") else: common.set_error_message("The session was not entirely removed!") elif cherrypy.request.method == 'POST' and remove_figure and figure_id is not None: success = self.figure_service.remove_result_figure(figure_id) if success: common.set_info_message("Figure removed successfully!") else: common.set_error_message("Figure could not be removed!") elif figure_id is not None: self._update_figure(figure_id, **data) self.redirect(redirect_url)
def _update_figure(self, figure_id, **data): """ Updates the figure details to the given data. """ try: data = EditPreview().to_python(data) self.figure_service.edit_result_figure(figure_id, **data) common.set_info_message('Figure details updated successfully.') return True except formencode.Invalid as excep: self.logger.debug(excep) common.set_error_message(excep.message) return False
[docs] @cherrypy.expose @handle_error(redirect=False) @check_user def downloadimage(self, figure_id): """ Allow a user to download a figure. """ figure = self.figure_service.load_figure(figure_id) image_folder = self.storage_interface.get_images_folder(figure.project.name) figure_path = os.path.join(image_folder, figure.file_path) return serve_file(figure_path, "image/" + figure.file_format, "attachment", "%s.%s" % (figure.name, figure.file_format))
[docs] @cherrypy.expose @handle_error(redirect=False) @using_template("overlay") @check_user def displayzoomedimage(self, figure_id): """ Displays the image with the specified id in an overlay dialog. """ figure = self.figure_service.load_figure(figure_id) figures_folder = self.storage_interface.get_images_folder(figure.project.name) figure_full_path = os.path.join(figures_folder, figure.file_path) figure_file_path = utils.path2url_part(figure_full_path) description = figure.session_name + " - " + figure.name template_dictionary = dict(figure_file_path=figure_file_path) return self.fill_overlay_attributes(template_dictionary, "Detail", description, "project/figure_zoom_overlay", "lightbox")
[docs]class EditPreview(formencode.Schema): """ Validate edit action on Stored Preview """ name = formencode.All(validators.UnicodeString(not_empty=True)) session_name = formencode.All(validators.UnicodeString(not_empty=True))