Quickstart Visualization

Visualization implies to have a GUI, which will help to display many things: graphs, text, 3D representations, … This software provides a clean interface to PyQt. PyQt works that way:

  • A QMainWindow that includes layouts, (ex: horizontal, vertical, grid, …)
  • Layouts can include widgets.
  • Widgets can be anything: buttons, menu, opengl 3D representation, graphs, … Several high-level widgets are proposed, check optimeed.visualize.gui.widgets .

Simple gui using OpenGL:

This example shows how to create a simple gui that contains an openGL widget. First define the imports:

from optimeed.visualize.gui.widgets.widget_openGL import widget_openGL
from optimeed.visualize.gui.gui_mainWindow import gui_mainWindow

from optimeed.visualize.gui.widgets.openGLWidget.DeviceDrawerInterface import DeviceDrawerInterface
from optimeed.core.interfaceDevice import InterfaceDevice
from optimeed.visualize.gui.widgets.openGLWidget.OpenGlFunctions_Library import *
from optimeed.visualize.gui.widgets.openGLWidget.Materials_visual import *

Define the device to draw

class Cone(InterfaceDevice):
    def __init__(self):
        self.radius_base = 1
        self.height = 1.5

Define the drawer

class ConeDrawer(DeviceDrawerInterface):
    def __init__(self):
        self.theCone = None

    def draw(self, theCone):  # How to draw the cone
        self.theCone = theCone
        glPushMatrix()  # Remove the previous matrices transformations
        glTranslate(0, 0, -theCone.height/2)  # Move the cone
        Bronze_material.activateMaterialProperties()  # Change colour aspect of the cones
        draw_disk(0, theCone.radius_base, 50, translate=theCone.height)  # Draw the base
        gluCylinder(gluNewQuadric(), 0, theCone.radius_base, theCone.height, 50, 10)  # Draw the cylinder
        glPopMatrix()  # Push back previous matrices transformations

    def get_init_camera(self, theDevice):
        tipAngle = 10
        viewAngle = 10
        zoomLevel = 0.5
        return tipAngle, viewAngle, zoomLevel

    def keyboard_push_action(self, theKey):
        if theKey == ord(b'H'):
            self.theCone.radius_base += 0.2  # Change the radius length when h is pressed

Instantiates objects and run the code

openGlWidget = widget_openGL()
theDrawer = ConeDrawer()
theCone = Cone()
openGlWidget.set_deviceDrawer(theDrawer)
openGlWidget.set_deviceToDraw(theCone)
myWindow = gui_mainWindow([openGlWidget], keep_alive=True)
myWindow.run()

Advanced visualization:

This example truly shows the potential of this tool, by linking saved data to graphs.

First, define the imports:

from optimeed.core import Collection
# Visuals imports
from optimeed.core.linkDataGraph import LinkDataGraph, HowToPlotGraph
from optimeed.visualize.gui.gui_mainWindow import gui_mainWindow
# Graph visuals imports
from optimeed.visualize.gui.widgets.widget_graphs_visual import widget_graphs_visual
from optimeed.visualize.gui.widgets.graphsVisualWidget.examplesActionOnClick import *
from optimeed.visualize.gui.widgets.graphsVisualWidget.smallGui import guiPyqtgraph
# OpenGL imports
from optimeed.visualize.gui.widgets.widget_openGL import widget_openGL
from optimeed.visualize.gui.widgets.openGLWidget.DeviceDrawerInterface import DeviceDrawerInterface
from optimeed.visualize.gui.widgets.openGLWidget.OpenGlFunctions_Library import *
from optimeed.visualize.gui.widgets.openGLWidget.Materials_visual import *

import os

Then, define an openGL drawer:

class Drawer(DeviceDrawerInterface):
    def __init__(self):
        self.theDevice = None

    def draw(self, theDevice):
        self.theDevice = theDevice
        glPushMatrix()
        Bronze_material.activateMaterialProperties()
        draw_simple_rectangle(theDevice.x, theDevice.y)
        glPopMatrix()

    def get_init_camera(self, theDevice):
        return 0, 0, 0.5

Load data files. Path is relative to this directory __file__:

collection_devices = Collection.load(os.path.join(os.path.dirname(__file__), 'resources/autosaved.col'), doCoherence=False)
collection_logOpti = Collection.load(os.path.join(os.path.dirname(__file__), 'resources/logopti.col'), doCoherence=False)

Instantiates high level module that links the data contained in collections to graphs (that will be later created):

theDataLink = LinkDataGraph()
id_logOpti = theDataLink.add_collection(collection_logOpti)
id_devices = theDataLink.add_collection(collection_devices)

The attributes to plots on x and y axis, and additional kwargs.:

howToPlot = HowToPlotGraph('objectives[0]', 'objectives[1]', {'x_label': "Objective 1", 'y_label': "Objective 2", 'is_scattered': True})

The trick here is that the objective functions is not directly stocked in collection_devices but in collection_logOpti. So we display the objectives coming from collection_logOpti but we link collection_devices from it:

howToPlot.exclude_col(id_devices)
theDataLink.link_collection_to_graph_collection(id_logOpti, id_devices)  # Link the devices to the logopti

Generate the graphs:

theDataLink.add_graph(howToPlot)
theGraphs = theDataLink.createGraphs()

Add additional actions to perform when the graph is clicked. This is what makes this software extremely powerful.:

theActionsOnClick = list()

openGlDrawing = widget_openGL()
openGlDrawing.set_deviceDrawer(Drawer())

theActionsOnClick.append(on_graph_click_showAnim(theDataLink, DataAnimationOpenGL(openGlDrawing)))
theActionsOnClick.append(on_graph_click_showInfo(theDataLink, visuals=[Repr_opengl(Drawer())]))
theActionsOnClick.append(on_click_extract_pareto(theDataLink, max_x=False, max_y=False))
theActionsOnClick.append(on_graph_click_delete(theDataLink))

Create the widget of the graphs, and the associated GUI:

myWidgetGraphsVisuals = widget_graphs_visual(theGraphs, highlight_last=True, refresh_time=-1)
guiPyqtgraph(myWidgetGraphsVisuals, actionsOnClick=theActionsOnClick)  # Add GUI to change action easily and export graphs
myWidgetGraphsVisuals = myWidgetGraphsVisuals

Launch the window:

myWindow = gui_mainWindow([myWidgetGraphsVisuals], keep_alive=True)
myWindow.run()