JobPlugin.py 6.68 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
#------------------------------------------------------------------------------------------
#Copyright (C)
#2015- Eric C. Pellegrini Institut Laue-Langevin
#BP 156
#6, rue Jules Horowitz
#38042 Grenoble Cedex 9
#France
#pellegrini[at]ill.fr
#goret[at]ill.fr
#aoun[at]ill.fr
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library 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
#Lesser General Public License for more details.
#
#You should have received a copy of the GNU Lesser General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

''' 
Created on Apr 14, 2015

eric pellegrini's avatar
eric pellegrini committed
30
:author: Eric C. Pellegrini
31 32 33 34 35
'''

import os
import subprocess               
import sys
eric pellegrini's avatar
eric pellegrini committed
36
import tempfile
37 38 39 40 41
import time

import wx
import wx.aui as aui

42
from MDANSE import PLATFORM,REGISTRY
43
from MDANSE.Framework.InputData.EmptyData import EmptyData
44 45 46 47

from MDANSE.GUI import PUBLISHER
from MDANSE.GUI.DataController import DATA_CONTROLLER
from MDANSE.GUI.Plugins.ComponentPlugin import ComponentPlugin
48 49 50 51 52 53 54
from MDANSE.GUI.ComboWidgets.ConfigurationPanel import ConfigurationPanel
from MDANSE.GUI.ComboWidgets.JobHelpFrame import JobHelpFrame

class JobPlugin(ComponentPlugin):
        
    def __init__(self, parent, *args, **kwargs):
                
55
        self._job = REGISTRY["job"][self._type]()
56
        
57
        ComponentPlugin.__init__(self, parent, size=wx.Size(800,600), *args, **kwargs)
58 59 60 61 62 63 64 65
                
    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)
                
66
        self._parametersPanel = ConfigurationPanel(self._main, self._job)
67 68 69 70 71 72 73 74 75
                    
        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)
76
        sbSizer.Add((-1,-1), 1, wx.ALL|wx.EXPAND, 5)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        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):
                                
97
        d = JobHelpFrame(self,self._job)
98 99 100 101 102

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

103
        if not self._parametersPanel.validate():
104
            return
105 106

        parameters = self._parametersPanel.get_value() 
107
        
108
        name = self._job.define_unique_name()
eric pellegrini's avatar
eric pellegrini committed
109 110 111 112 113

        handle,filename = tempfile.mkstemp(prefix="MDANSE_%s.py" % name, text=True)
        os.close(handle)
                        
        self._job.save(filename, parameters)
114
                                
115
        try:
116 117 118 119 120 121
            from subprocess import DEVNULL
        except ImportError:
            DEVNULL = os.open(os.devnull, os.O_RDWR)
            
        try:
            subprocess.check_output([sys.executable, filename], stdin=DEVNULL, stderr=DEVNULL)
122
        except subprocess.CalledProcessError as e:
123
            message = e.output
124
        else:        
125 126 127 128
            message = None

        time.sleep(1)
        PUBLISHER.sendMessage("msg_start_job",message=message)
129 130 131
        
    def on_save(self, event=None):

132
        if not self._parametersPanel.validate():
133
            return
134 135

        parameters = self._parametersPanel.get_value() 
136 137 138 139 140 141 142 143 144 145 146 147 148
        
        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"
                        
149
        self._job.save(path, parameters)
150 151 152

    def plug(self):
                
153
        self._parent._mgr.GetPane(self).Float().Center().Floatable(True).Dockable(True).CloseButton(True)
154
                
155
        self._parent._mgr.Update()
156
                    
157
        PUBLISHER.sendMessage("msg_set_data", message=self)
158 159 160 161 162 163 164
                        
    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
165
    def __init__(self, parent, jobType, datakey=None):
166
                
167
        wx.Frame.__init__(self, parent, wx.ID_ANY, style=wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.MAXIMIZE_BOX|wx.RESIZE_BORDER)
168 169 170

        self._jobType = jobType

171
        job = REGISTRY['job'][self._jobType]
172
        
173
        self.SetTitle(job.label)
174
                
175 176 177 178
        data = REGISTRY['input_data'][job.ancestor[0]](datakey,True)

        self.datakey = data.name
                          
179 180
        if not isinstance(data,EmptyData):
            DATA_CONTROLLER[data.name] = data
181 182
                        
        plugin = REGISTRY['plugin'][self._jobType](self)
183 184

        self.SetSize(plugin.GetSize())
185
        
186
        PUBLISHER.sendMessage("msg_set_data", message=plugin)
187
                        
188
if __name__ == "__main__":
189 190
            
    filename = os.path.join(os.path.dirname(PLATFORM.package_directory()),'Data','Trajectories','MMTK','protein_in_periodic_universe.nc')
191 192
    
    app = wx.App(False)
193
    f = JobFrame(None,'dacf',filename)
194
    f.Show()
195
    app.MainLoop()