2""" @brief  Evolife Window system                                                 """ 
    4#============================================================================# 
    5# EVOLIFE  http://evolife.telecom-paris.fr             Jean-Louis Dessalles   
   16if __name__ == 
'__main__':  sys.path.append(
'../..')  
 
   18try:    
from PyQt5 
import QtGui, QtCore, QtWidgets
 
   20        from PyQt4 
import QtGui, QtCore
 
   21        from PyQt4 
import QtGui 
as QtWidgets
 
   34DefaultIconName = 
'Graphics/EvolifeIcon.png' 
   35HelpFileName = 
'Help.txt' 
   45    """ Controls the simulation, either step by step, or in 
   49    def __init__(self, SimulationStep, Obs, method='timer'): 
   50        """ Stores Obs as observer  
   51            and SimulationStep 
as the function that processes one step of the simulation.
 
   52            'method' can be 
'timer' or 'thread' (
'timer' preferred)
 
   66        """ Entering in 'Run' mode 
   74        """ Entering in 'Step' mode 
   83        """ Stops the simulation thread or timer 
   86            if self.
timer is not None and self.
timer.isActive():
 
   88        elif self.
method == 
'thread':
 
   99        """ (re)starts the simulation thread or timer 
  102        if self.
method == 
'timer':
 
  104                if self.
timer is None:
 
  105                    self.
timer = QtCore.QTimer()
 
  110        elif self.
method == 
'thread':
 
  117        """ calls Simulation_launch 
  122        """ calls SimulationStep 
  130                traceback.print_exc()
 
  164    """ Minimal control panel with [Run] [Step] [Help] and [quit] buttons 
  168        """ Creates a window with buttons that is also a Simulation_Control 
  170        self.Name = Obs.get_info('Title')
 
  173        Simulation_Control.__init__(self, SimulationStep, Obs, method=
'timer')
 
  174        Evolife_Graphic.Active_Frame.__init__(self, parent=
None, control=self)
 
  176            self.setWindowTitle(self.
Name)
 
  177        self.setWindowIcon(QtGui.QIcon(os.path.join(self.
Obs.get_info(
'EvolifeMainDir'), self.
IconName)))
 
  193        NameLabel = QtWidgets.QLabel(
"<font style='color:blue;font-size:17px;font-family:Comic Sans MS;font-weight:bold;'>%s</font>" % self.
Name.upper(), self)
 
  194        NameLabel.setAlignment(QtCore.Qt.AlignHCenter)
 
  196        AdrLabel = QtWidgets.QLabel(
"<a href=http://www.dessalles.fr/%s>www.dessalles.fr/%s</a>" % (self.
Name.replace(
' ',
'_'), self.
Name), self)
 
  197        AdrLabel.setAlignment(QtCore.Qt.AlignHCenter)
 
  229        self.setGeometry(*Screen_.locate(200, 200, 140, 300))       
 
  233    def LocalButton(self, ParentFrame, ButtonType, Text, Tip, ClickFunction, ShortCutKey=None):
 
  236        Button = ButtonType(Text, self) 
  237        Button.setToolTip(Tip) 
  238        Button.clicked.connect(ClickFunction) 
  239        if ShortCutKey 
is not None:
 
  240            Button.setShortcut(QtGui.QKeySequence(ShortCutKey))
 
  241        ParentFrame.addWidget(Button)
 
  245        """ opens Web browser with provided address 
  250        """ Displays a text file named: Help.txt 
  254            self.
SWindows[
'Help'].setWindowIcon(QtGui.QIcon(os.path.join(self.
Obs.get_info(
'EvolifeMainDir'),self.
IconName)))
 
  256                self.
SWindows[
'Help'].
display(os.path.join(self.
Obs.get_info(
'EvolifeMainDir'), HelpFileName))
 
  257                self.
SWindows[
'Help'].setGeometry(*Screen_.locate(400, 120, 600, 500))      
 
  260                self.
Obs.TextDisplay(
"Unable to find help file %s" % HelpFileName)
 
  265        """ closes the window 
  272        """ puts the window in front of display 
  274        if self.isActiveWindow():
 
  275            for SWName 
in self.SWindows:
 
  276                self.SWindows[SWName].raise_()
 
  278                SWName = random.choice(list(self.SWindows.keys()))
 
  279                self.SWindows[SWName].
Raise()               
 
  282            self.activateWindow()
 
  286        """ close satelite windows and stops the simulation 
  289        self.simulation_steady_mode = 
False  
  290        for (SWName,SW) 
in list(self.SWindows.items()): 
 
  291            self.SWindows[SWName].close()        
 
  293        self.Simulation_stop()
 
  297        """ A satellite window has been destroyed - removes it from the list 
  299        for SWName 
in self.SWindows:
 
  300            if self.SWindows[SWName] == SW:
 
  301                del self.SWindows[SWName]
 
  303        error(
'Evolife_Window', 
'Unidentified destroyed window')
 
  306        """ Processes graphic orders if in visible state 
  307            returns -1 if Observer says the simulation 
is over
 
  309        Simulation_Control.ReturnFromThread(self)    
  310        if self.Obs.Visible():  self.Process_graph_orders()
 
  311        if self.Obs.Over(): 
return -1   
 
  315        """ Just let Observer know that display has taken place 
  318        self.CurrentFrame += 1             
 
  319        if self.PhotoMode == 1:
 
  324        """ processes actions such as Run, Step, Help... 
  326        if e.key() 
in [QtCore.Qt.Key_Q, QtCore.Qt.Key_Escape]:
 
  328        elif e.key() 
in [QtCore.Qt.Key_S, QtCore.Qt.Key_Space]: 
 
  329            self.StepButtonClick()
 
  330        elif e.key() 
in [QtCore.Qt.Key_R, QtCore.Qt.Key_C]:
 
  331            self.Buttons[
'Run'].animateClick()
 
  332        elif e.key() 
in [QtCore.Qt.Key_H, QtCore.Qt.Key_F1]:
 
  333            self.Buttons[
'Help'].animateClick()
 
  334        elif e.key() 
in [QtCore.Qt.Key_M]:  
 
  337        try:    self.Obs.inform(str(e.text()))
 
  338        except UnicodeEncodeError:  
pass 
  341        """ Sends event to observer (useful for mouse events) 
  344        self.Obs.recordInfo(Event.EventType, (Event.EmittingClass, Event.Info))
 
  351    """ This class combines a control panel and a slider for controlling display period 
  354    def __init__(self, SimulationStep, Obs, Background=None):
 
  355        """ Create Control frame + displayperiod slider 
  358        Simulation_Control_Frame.__init__(self, SimulationStep, Obs) 
  361        self.
lcd = QtWidgets.QLCDNumber(self)
 
  362        self.
lcd.SegmentStyle(QtWidgets.QLCDNumber.Filled)
 
  363        lcdPalette = QtGui.QPalette()
 
  364        lcdPalette.setColor(QtGui.QPalette.Light, QtGui.QColor(200,10,10))
 
  365        self.
lcd.setPalette(lcdPalette)
 
  376        """ The displayed value varies exponentially with the slider's position 
  379        if (disp > 2999):   disp = ((disp+500) // 1000) * 1000
 
  380        elif (disp > 299):  disp = ((disp+50) // 100) * 100
 
  381        elif (disp > 29):   disp = ((disp+5) // 10) * 10
 
  382        elif (disp > 14):   disp = ((disp+2) // 5) * 5
 
  390        if Period == 0: Period = 1
 
  402    """ This class combines a control panel and a space to display curves 
  405    def __init__(self, SimulationStep, Obs, Background=None):
 
  406        """ Creates a plot area and displays it to the right of the control frame 
  409        Simulation_Display_Control_Frame.__init__(self, SimulationStep, Obs) 
  410        self.setGeometry(*Screen_.locate(50, 50, 702, 420))      
  426        """ Displays a text file named:   
  430            self.
SWindows[
'Legend'].setWindowIcon(QtGui.QIcon(os.path.join(self.
Obs.get_info(
'EvolifeMainDir'),self.
IconName)))
 
  432                self.
plot_area.Area.Curvenames(self.
Obs.get_info(
'CurveNames')) 
 
  433                Comments = self.
Obs.get_info(
'WindowLegends')
 
  436                self.
SWindows[
'Legend'].setGeometry(*Screen_.locate(50, 550, 600, 150))     
 
  439                self.
Obs.TextDisplay(
"Unable to find information on curves")
 
  447        """ Processes graph orders received from observer. 
  448            Displays PlotData by adding points to curves and by displaying them.
 
  454                self.
Obs.TextDisplay(
'%s Created' % ImgC)
 
  456        PlotData = self.
Obs.get_info(
'PlotOrders')
 
  458            for (CurveId, Point) 
in PlotData:
 
  459                self.
plot_area.Area.plot(CurveId, Point, Width=3*Screen_.ratio)
 
  460        Simulation_Control_Frame.Process_graph_orders(self)
 
  463        """ store and print simulation results   
  466        RF = self.
Obs.get_info(
'ResultFile')
 
  468            self.
plot_area.Area.Curvenames(self.
Obs.get_info(
'CurveNames')) 
 
  469            AverageValues = self.
plot_area.Area.dump(RF, self.
Obs.get_info(
'ResultHeader'), 
 
  470                                        self.
Obs.get_info(
'ResultOffset', 0))
 
  472                self.
Obs.TextDisplay(
'\n. ' + 
'\n. '.join([
'%s\t%s' % (C, AverageValues[C]) 
for C 
in sorted(AverageValues)]))
 
  473                self.
Obs.TextDisplay(
'\nResults stored in %s*.csv' % os.path.normpath(RF))
 
  476        """ close parent closeEvent 
  480        Simulation_Control_Frame.closeEvent(self, event)
 
  488    """ Defines Evolife main window by modification of the generic Simulation Frame 
  491    def __init__(self, SimulationStep, Obs, Capabilities='C', Options=[]):
 
  492        """ Creation of the main window and active satelite windows 
  505        if Obs.get_info(
'Background') 
is not None:
 
  506            self.
Background[
'Default'] = Obs.get_info(
'Background')
 
  507        for W 
in [
'Curves', 
'Genomes', 
'Photo', 
'Trajectories', 
'Network', 
'Field', 
'Log', 
'Image']:
 
  508            self.
Background[W] = Obs.get_info(W + 
'Wallpaper')
 
  516            Simulation_Frame.__init__(self, SimulationStep, Obs, Background=self.
Background[
'Curves'])
 
  517        elif set(
'FRGNT') & set(Capabilities):
 
  518            self.
ParentClass = Simulation_Display_Control_Frame
 
  519            Simulation_Display_Control_Frame.__init__(self, SimulationStep, Obs)
 
  522            Simulation_Control_Frame.__init__(self, SimulationStep, Obs)
 
  549        DefViews = self.
Obs.get_info(
'DefaultViews')
 
  554                if type(B) == str:  self.
Buttons[B].animateClick()
 
  555                elif type(B) == tuple:
 
  556                    self.
Buttons[B[0]].animateClick()
 
  564        elif DefViews 
is None:
 
  565            for B 
in [
'Trajectories', 
'Field', 
'Network', 
'Genomes', 
'Log']:    
 
  572            self.
Buttons[
'Run'].animateClick()
 
  576        """ recognizes shortcuts to show satelite windows (Genomes, Trajectories, Field, Legend, Film...) 
  581            if e.key() == QtCore.Qt.Key_G:  self.
Buttons[
'Genomes'].animateClick()
 
  582            if e.key() == QtCore.Qt.Key_P:  self.
Buttons[
'Photo'].animateClick()
 
  583            if e.key() == QtCore.Qt.Key_T:  self.
Buttons[
'Trajectories'].animateClick()
 
  584            if e.key() == QtCore.Qt.Key_N:  self.
Buttons[
'Network'].animateClick()
 
  585            if e.key() == QtCore.Qt.Key_F:  self.
Buttons[
'Field'].animateClick()
 
  586            if e.key() == QtCore.Qt.Key_L:  self.
Buttons[
'Log'].animateClick()      
 
  587            if e.key() == QtCore.Qt.Key_I:  self.
Buttons[
'Image'].animateClick()        
 
  588            if e.key() == QtCore.Qt.Key_D:  self.
Buttons[
'Legend'].animateClick()       
 
  590        except KeyError:    
pass 
  594        if 'Genomes' not in self.
Buttons:   
return 
  597                                                                outputDir=self.
Obs.get_info(
'OutputDir'), 
 
  598                                                                image=self.
Background[
'Genomes'], zoom=Screen_.ratio)
 
  600            self.
SWindows[
'Genomes'].move(*Screen_.locate(800, 200))        
 
  605        """ saves a snapshot of the simulation and goes to stepwise mode 
  607        if 'Photo' not in self.
Buttons: 
return 
  609            self.
Obs.TextDisplay(
'Photo mode ended\n')
 
  614            self.
Obs.TextDisplay(
'\nPhoto mode' + self.
Obs.__str__() + 
'\n' + 
'Frame %d' % self.
CurrentFrame)
 
  618        """ Film mode is activated by pressing the 'V' key (video) 
  619            It results in images (snapshots) being saved each time Observer 
is 'visible' 
  621        if 'Photo' not in self.
Buttons: 
return 
  625            self.setWindowTitle(
"%s (FILM MODE)" % self.
Name)
 
  626        else:   self.setWindowTitle(self.
Name)
 
  629        """ displays the 'Trajectories' window 
  631        if 'Trajectories' not in self.
Buttons:  
return 
  632        if 'Trajectories' not in self.
SWindows:
 
  634                                                Wtitle=
'Trajectories', 
 
  635                                                outputDir=self.
Obs.get_info(
'OutputDir'), 
 
  636                                                image=self.
Background[
'Trajectories'], zoom=Screen_.ratio)
 
  638            self.
SWindows[
'Trajectories'].move(*Screen_.locate(275, 500))       
 
  643        """ displays the 'Network' window 
  645        if 'Network' not in self.
Buttons:   
return 
  648                                                outputDir=self.
Obs.get_info(
'OutputDir'), 
 
  649                                                image=self.
Background[
'Network'], zoom=Screen_.ratio)
 
  651            self.
SWindows[
'Network'].move(*Screen_.locate(790, 500))
 
  655        """ displays the 'Field' window 
  657        if 'Field' not in self.
Buttons: 
return 
  661                                                outputDir=self.
Obs.get_info(
'OutputDir'), 
 
  662                                                image=self.
Background[
'Field'], zoom=Screen_.ratio)
 
  664            self.
SWindows[
'Field'].move(*Screen_.locate(800, 100))      
 
  669        """ [not implemented] 
  671        if 'Log' not in self.
Buttons:   
return 
  672        self.
Obs.TextDisplay(
'LogTerminal\n')
 
  676        """ Sets Satellite window's geometry, icon and title 
  678        self.SWindows[WindowName].setWindowIcon(QtGui.QIcon(os.path.join(self.Obs.get_info('EvolifeMainDir'),self.
IconName)))
 
  687        """ sets the availability of the 'Network', 'Field', 'Image', 'Trajectories' tick button on display 
  690            if B 
in [
'Network', 
'Field', 
'Image', 
'Trajectories', 
'Log']:
 
  692                    self.
Buttons[B].setCheckState(
False)
 
  694                    self.
Buttons[B].setCheckState(
True)
 
  697        """ Processes graph orders received from observer. 
  698            Parent class displays PlotData by adding points to curves and by displaying them.
 
  699            In addition, gets orders 
for satelite windows 
from Oberver 
and processes them.
 
  702        ImgG, ImgN, ImgF, ImgT = ('',) * 4
 
  704            ImgG = self.
SWindows[
'Genomes'].genome_display(genome=self.
Obs.get_data(
'DNA'),
 
  705                                                    gene_pattern=self.
Obs.get_info(
'GenePattern'),
 
  708            ImgN = self.
SWindows[
'Network'].Network_display(self.
Obs.get_data(
'Field', Consumption=
False),
 
  709                                                        self.
Obs.get_data(
'Network'),
 
  712            self.
SWindows[
'Field'].image_display(self.
Obs.get_info(
'Image'), windowResize=
True)
 
  713            ImgF = self.
SWindows[
'Field'].Field_display(self.
Obs.get_data(
'Field'), 
 
  718            self.
SWindows[
'Trajectories'].image_display(self.
Obs.get_info(
'Pattern'), windowResize=
True)
 
  719            ImgT = self.
SWindows[
'Trajectories'].Field_display(self.
Obs.get_data(
'Trajectories'),
 
  723            if ''.join([ImgG, ImgN, ImgF, ImgT]):
 
  724                self.
Obs.TextDisplay(
'%s Created' % 
' '.join([ImgG, ImgN, ImgF, ImgT]))
 
  729        """ Exits if 'ExitOnEnd' is True 
  731        if 'ExitOnEnd' in self.
DOptions and self.
DOptions[
'ExitOnEnd'] 
in [
True, 
'Yes']:
 
  734            self.
Buttons[
'Quit'].animateClick() 
 
  749def Start(SimulationStep, Obs, Capabilities='C', Options={}):
 
  750    """ SimulationStep is a function that performs a simulation step 
  751        Obs is the observer that stores statistics
 
  752        Capabilities (curves, genome display, trajectory display...)
 
  753            = any string of letters 
from: CFGNTP
 
  755            F = Field (2D seasonal display) (excludes R)
 
  757            I = Image (same 
as Field, but no slider)
 
  759            N = social network display
 
  760            P = Photo (screenshot)
 
  761            R = Region (2D ongoing display) (excludes F)
 
  762            T = Trajectory display
 
  765        - Run:
True  means that the simulation will run automatically
 
  766        - Background:<Colour 
or image>
 
  767        - ExitOnEnd:
True    doesn
't pause when simulation stops 
  771    MainApp = QtWidgets.QApplication(sys.argv) 
  774    Screen_ = Screen.Screen_(MainApp)   # stores physical dimensions of display 
  775    Screen_.switchScreen() 
  777    if set(Capabilities) <= set('CFGILNPRT'): 
  779        MainWindow = 
Evolife_Frame(SimulationStep, Obs, Capabilities, Options)
 
  784        MainApp.deleteLater()   
 
  787        print(
"""   Error: <Capabilities> should be a string of letters taken from: 
 
  789        F = Field (2D seasonal display) (excludes R)
 
  791        I = Image (same 
as Field, but no slider)
 
  793        N = social network display
 
  794        P = Photo (screenshot)
 
  795        R = Region (2D ongoing display) (excludes F)
 
  796        T = Trajectory display
 
  802if __name__ == 
'__main__':
 
  807__author__ = 
'Dessalles' 
An Active_frame reacts to basic keyboard control.
 
def Raise(self)
puts the window on top of display
 
Standard canvas plus resizing capabilities.
 
def photo(self, Name, FrameNumber=-1, outputDir='.', extension='png')
takes a snapshot and saves it to a new file
 
A graphic area that displays moving agents #.
 
Genome_window: An image area that displays binary genomes.
 
Displays a text file supposed to provide help.
 
displays legend for curves
 
Network_window: A drawing area that displays social links The population is displayed twice,...
 
Synonymous for Field_window.
 
Defines Evolife main window by modification of the generic Simulation Frame.
 
FieldOngoingDisplay
Control panel #.
 
def __init__(self, SimulationStep, Obs, Capabilities='C', Options=[])
Creation of the main window and active satelite windows.
 
def TrajectoryButtonClick(self, event)
displays the 'Trajectories' window
 
def NetworkButtonClick(self, event)
displays the 'Network' window
 
def PhotoButtonClick(self, event)
saves a snapshot of the simulation and goes to stepwise mode
 
def FieldButtonClick(self, event)
displays the 'Field' window
 
def WindowActivation(self, WindowName)
Sets Satellite window's geometry, icon and title.
 
def SWDestroyed(self, SW)
 
def keyPressEvent(self, e)
recognizes shortcuts to show satelite windows (Genomes, Trajectories, Field, Legend,...
 
def DecisionToEnd(self)
Exits if 'ExitOnEnd' is True.
 
def GenomeButtonClick(self, event)
 
def FilmButtonClick(self, event)
Film mode is activated by pressing the 'V' key (video) It results in images (snapshots) being saved e...
 
def LogButtonClick(self, event)
[not implemented]
 
def Process_graph_orders(self)
Processes graph orders received from observer.
 
def checkButtonState(self)
sets the availability of the 'Network', 'Field', 'Image', 'Trajectories' tick button on display
 
Capabilities
Creation of the main window #.
 
def closeEvent(self, event)
close parent closeEvent
 
Minimal control panel with [Run] [Step] [Help] and [quit] buttons.
 
def QuitButtonClick(self, event)
closes the window
 
def __init__(self, SimulationStep, Obs)
Creates a window with buttons that is also a Simulation_Control.
 
def LocalButton(self, ParentFrame, ButtonType, Text, Tip, ClickFunction, ShortCutKey=None)
Creates a button.
 
def HelpButtonClick(self, event=None)
Displays a text file named: Help.txt.
 
SWindowsPreferredGeometry
 
def EvolifeWebSite(self, e)
opens Web browser with provided address
 
SWindows
List and status of Satellite windows.
 
Interface with the simulation thread #.
 
def OneStep(self)
calls SimulationStep
 
def Simulation_resume(self)
calls Simulation_launch
 
def StepButtonClick(self, event=None)
Entering in 'Step' mode.
 
def RunButtonClick(self, event=None)
Entering in 'Run' mode.
 
simulation
Status of the simulation programme.
 
def Simulation_launch(self, continuous_mode)
(re)starts the simulation thread or timer
 
def DecisionToEnd(self)
to be overloaded
 
def ReturnFromThread(self)
to be overloaded
 
def Simulation_stop(self)
Stops the simulation thread or timer.
 
This class combines a control panel and a slider for controlling display period.
 
def DisplayPeriodSet(self, Period, FlagForce=True)
 
def __init__(self, SimulationStep, Obs, Background=None)
Create Control frame + displayperiod slider.
 
def DisplayPeriodChanged(self, event)
The displayed value varies exponentially with the slider's position.
 
This class combines a control panel and a space to display curves.
 
def dump(self, verbose=False)
store and print simulation results
 
def __init__(self, SimulationStep, Obs, Background=None)
Creates a plot area and displays it to the right of the control frame.
 
def LegendButtonClick(self, event=None)
Displays a text file named:
 
def closeEvent(self, event)
close parent closeEvent
 
def Process_graph_orders(self)
Processes graph orders received from observer.
 
Graphic area for displaying curves #.
 
def display(self)
calling 'display' for all individuals in the population
 
def Start(SimulationStep, Obs, Capabilities='C', Options={})
SimulationStep is a function that performs a simulation step Obs is the observer that stores statisti...
 
def closeEvent(self, event)
close satelite windows and stops the simulation
 
def keyPressEvent(self, e)
processes actions such as Run, Step, Help...
 
def ReturnFromThread(self)
Processes graphic orders if in visible state returns -1 if Observer says the simulation is over.
 
def Raise(self)
if self.closeEvent(None): QtCore.QCoreApplication.instance().quit()
 
def SWDestroyed(self, SW)
A satellite window has been destroyed - removes it from the list.
 
def EventInterpreter(self, Event)
Sends event to observer (useful for mouse events)
 
def Process_graph_orders(self)
Just let Observer know that display has taken place.