JobPlugin.py 6.62 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# **************************************************************************
#
# MDANSE: Molecular Dynamics Analysis for Neutron Scattering Experiments
#
# @file      Src/GUI/Plugins/JobPlugin.py
# @brief     Implements module/class/test JobPlugin
#
# @homepage  https://mdanse.org
# @license   GNU General Public License v3 or higher (see LICENSE)
# @copyright Institut Laue Langevin 2013-now
# @authors   Scientific Computing Group at ILL (see AUTHORS)
#
# **************************************************************************

15
16
17
import os
import subprocess               
import sys
eric pellegrini's avatar
eric pellegrini committed
18
import tempfile
19
20
21
22
23
import time

import wx
import wx.aui as aui

24
from MDANSE import PLATFORM,REGISTRY
25
from MDANSE.Framework.InputData.EmptyData import EmptyData
26
27
28
29

from MDANSE.GUI import PUBLISHER
from MDANSE.GUI.DataController import DATA_CONTROLLER
from MDANSE.GUI.Plugins.ComponentPlugin import ComponentPlugin
30
31
32
33
34
35
36
from MDANSE.GUI.ComboWidgets.ConfigurationPanel import ConfigurationPanel
from MDANSE.GUI.ComboWidgets.JobHelpFrame import JobHelpFrame

class JobPlugin(ComponentPlugin):
        
    def __init__(self, parent, *args, **kwargs):
                
37
        self._job = REGISTRY["job"][self._type]()
38
        
39
        ComponentPlugin.__init__(self, parent, size=wx.Size(800,600), *args, **kwargs)
40
41
42
43
44
45
46
47
                
    def build_panel(self):
        
        self._main = wx.ScrolledWindow(self, wx.ID_ANY, size=self.GetSize())
        self._main.SetScrollbars(pixelsPerUnitX= 20, pixelsPerUnitY=20, noUnitsX=500, noUnitsY=500)
                
        mainSizer = wx.BoxSizer(wx.VERTICAL)
                
48
        self._parametersPanel = ConfigurationPanel(self._main, self._job)
49
50
51
52
53
54
55
56
57
                    
        sb = wx.StaticBox(self._main, wx.ID_ANY)
        sbSizer = wx.StaticBoxSizer(sb, wx.HORIZONTAL)

        helpButton = wx.Button(self._main, label = "Help")                                                        
        saveButton = wx.Button(self._main, label = "Save")
        runButton = wx.Button(self._main, label = "Run")

        sbSizer.Add(helpButton, 0, wx.ALL|wx.EXPAND, 5)
58
        sbSizer.Add((-1,-1), 1, wx.ALL|wx.EXPAND, 5)
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
        sbSizer.Add(saveButton, 0, wx.ALL|wx.EXPAND, 5)
        sbSizer.Add(runButton, 0, wx.ALL|wx.EXPAND, 5)

        mainSizer.Add(self._parametersPanel, 1, wx.ALL|wx.EXPAND, 0)
        mainSizer.Add(sbSizer, 0, wx.ALL|wx.EXPAND, 5)

        self._main.SetSizer(mainSizer)        
        mainSizer.Layout()
        self._main.Fit()
                
        self._mgr.AddPane(self._main, aui.AuiPaneInfo().Center().Floatable(False).Dock().CaptionVisible(False).CloseButton(False))

        self._mgr.Update()
        
        self.Bind(wx.EVT_BUTTON, self.on_help, helpButton)
        self.Bind(wx.EVT_BUTTON, self.on_save, saveButton)
        self.Bind(wx.EVT_BUTTON, self.on_run, runButton)
        
    def on_help(self, event):
                                
79
        d = JobHelpFrame(self,self._job)
80
81
82
83
84

        d.Show()
                         
    def on_run(self, event=None):

85
        if not self._parametersPanel.validate():
86
            return
87
88

        parameters = self._parametersPanel.get_value() 
89
        
90
        name = self._job.define_unique_name()
eric pellegrini's avatar
eric pellegrini committed
91
92
93
94
95

        handle,filename = tempfile.mkstemp(prefix="MDANSE_%s.py" % name, text=True)
        os.close(handle)
                        
        self._job.save(filename, parameters)
Remi Perenon's avatar
Remi Perenon committed
96
97
98
99
100
101
102
103
104
105
106
107
108
                            
        
        if PLATFORM.name == "windows":
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
        else:
            startupinfo = None

        #try:
        #    from subprocess import DEVNULL
        #except ImportError:
        #    DEVNULL = os.open(os.devnull, os.O_RDWR)
109
110
            
        try:
Remi Perenon's avatar
Remi Perenon committed
111
            subprocess.Popen([sys.executable, filename], startupinfo=startupinfo, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
112
        except subprocess.CalledProcessError as e:
113
            message = e.output
114
        else:        
115
            message = None
116
117
118
119
120
121
122

        PUBLISHER.sendMessage("msg_start_job",message=message)
        
        if message is None:
            d = wx.MessageDialog(None, 'Your analysis is performing. Do you want to close ?', 'Question', wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
            if d.ShowModal() == wx.ID_YES:
                self.on_close(None)
123
124
125
        
    def on_save(self, event=None):

126
        if not self._parametersPanel.validate():
127
            return
128
129

        parameters = self._parametersPanel.get_value() 
130
131
132
133
134
135
136
137
138
139
140
141
142
        
        d = wx.FileDialog(self, "Save MDANSE python script", style = wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT, wildcard = "Python files (*.py)|*.py")        
        if d.ShowModal() == wx.ID_CANCEL:
            return
        
        path = d.GetPath().strip()
                
        if not path:
            return
        
        if os.path.splitext(path)[1] != ".py":
            path += ".py"
                        
143
        self._job.save(path, parameters)
144
145
146

    def plug(self):
                
147
        self._parent._mgr.GetPane(self).Float().Center().Floatable(True).Dockable(True).CloseButton(True)
148
                
149
        self._parent._mgr.Update()
150
                    
151
        PUBLISHER.sendMessage("msg_set_data", message=self)
152
153
154
155
156
157
158
                        
    def on_close(self, event):
        
        self.parent.mgr.ClosePane(self.parent.mgr.GetPane(self))
        
class JobFrame(wx.Frame):
    
eric pellegrini's avatar
eric pellegrini committed
159
    def __init__(self, parent, jobType, datakey=None):
160
                
161
        wx.Frame.__init__(self, parent, wx.ID_ANY, style=wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.MAXIMIZE_BOX|wx.RESIZE_BORDER)
162
163
164

        self._jobType = jobType

165
        job = REGISTRY['job'][self._jobType]
166
        
167
        self.SetTitle(job.label)
168
                
169
170
171
172
        data = REGISTRY['input_data'][job.ancestor[0]](datakey,True)

        self.datakey = data.name
                          
173
174
        if not isinstance(data,EmptyData):
            DATA_CONTROLLER[data.name] = data
175
176
                        
        plugin = REGISTRY['plugin'][self._jobType](self)
177
178

        self.SetSize(plugin.GetSize())
179
        
180
        PUBLISHER.sendMessage("msg_set_data", message=plugin)
181
                        
182
if __name__ == "__main__":
183
184
            
    filename = os.path.join(os.path.dirname(PLATFORM.package_directory()),'Data','Trajectories','MMTK','protein_in_periodic_universe.nc')
185
186
    
    app = wx.App(False)
187
    f = JobFrame(None,'dacf',filename)
188
    f.Show()
189
    app.MainLoop()