source: palm/trunk/SCRIPTS/palm_jm @ 4403

Last change on this file since 4403 was 4393, checked in by maronga, 5 years ago

removed PALM_BIN dependencies in GUI tools

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 12.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#--------------------------------------------------------------------------------#
4# This file is part of the PALM model system.
5#
6# PALM is free software: you can redistribute it and/or modify it under the terms
7# of the GNU General Public License as published by the Free Software Foundation,
8# either version 3 of the License, or (at your option) any later version.
9#
10# PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# PALM. If not, see <http://www.gnu.org/licenses/>.
16#
17# Copyright 1997-2018  Leibniz Universitaet Hannover
18##--------------------------------------------------------------------------------#
19#
20# Current revisions:
21# -----------------
22#
23#
24# Former revisions:
25# -----------------
26# $Id: palm_jm 4393 2020-02-04 21:24:48Z banzhafs $
27# Removed PALM_BIN dependency
28#
29# 2825 2018-02-20 21:48:27Z maronga
30# Modified header
31#
32# 2718 2018-01-02 08:49:38Z maronga
33# Corrected "Former revisions" section
34#
35# 2696 2017-12-14 17:12:51Z kanani
36# Change in file header (GPL part)
37#
38# 2504 2017-09-27 10:36:13Z maronga
39# Bugfix: jobs were not loaded on start.
40#
41# 2484 2017-09-20 14:22:42Z maronga
42# Adapted for palmrun with USER_CODE always stored under /JOBS/name/USER_CODE/.
43# Added PALM logo
44#
45# 2068 2016-11-11 21:59:39Z maronga
46#
47# 2067 2016-11-11 21:55:49Z maronga
48# Minor bugfix: palm_jm can now be called from any location
49#
50# 2065 2016-11-11 12:25:10Z maronga
51# Initial revision
52#
53#
54# Description:
55# ------------
56# PALM job manager works a file manager for PALM input files. It lists all jobs in
57# the working directory and displays associated input and user code files, which
58# can be opened directly from the interface. Also, it is possible to copy jobs and
59# to create entire new sets of jobs based on a reference job.
60#
61# Instructions:
62# -------------
63# 1) Start palm_jm either from mrungui or from shell by "nohup palm_jm&"
64#
65# To do:
66# ------
67# 1) Add display for the MONITORING and OUTPUT folder
68# 2) Add zip function to export single or multiple jobs
69# 3) Allow for copying INPUT files to a remote host
70#------------------------------------------------------------------------------!
71
72import os
73from PyQt4 import QtGui, QtCore, uic
74from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
75import shutil
76import subprocess as sub
77import sys
78
79set_list = []
80
81
82
83# Determine PALM directories
84try: 
85   devnull = open(os.devnull, 'w')     
86   palm_dir = os.getcwd()
87   palm_bin = palm_dir + '/trunk/SCRIPTS'
88   job_dir = palm_dir + '/JOBS'
89   user_dir = palm_dir + '/USER_CODE'
90   with open(palm_bin + '/palm_jm', 'r') as fh:
91      # file found
92      out = None
93except:   
94   print ('Error. palm_jm probably called in wrong directory.')
95   raise SystemExit
96
97
98# MainWindow class
99class JobManager(QtGui.QMainWindow):
100
101       
102    def __init__(self):
103
104        super(JobManager, self).__init__()
105             
106        self.InitUi()         
107
108   
109    # Initialized MainWindow UI
110    def InitUi(self):
111
112        print(palm_bin + '/palm_jm_files/palm_jm.ui')
113
114        # Load predefined mainwindow
115        uic.loadUi(palm_bin + '/palm_jm_files/palm_jm.ui', self)
116
117        self.palm_logo.setPixmap(QtGui.QPixmap(palm_dir  + "/trunk/SCRIPTS/palmrungui_files/logo.png"))
118
119   
120        # Display MainWindow
121        self.show()
122       
123        QtGui.QApplication.processEvents()
124
125       
126        self.load_jobs()
127
128    def update_all(self):
129 
130       self.setEnabled(False)
131       self.list_input.clear() 
132       self.list_user.clear()
133       self.load_jobs()
134       self.setEnabled(True)
135
136    # Load jobs into list
137    def load_jobs(self):
138       
139       self.list_jobs.clear() 
140       self.push_copy.setEnabled(False)
141       self.push_create_set.setEnabled(False)     
142     
143       self.line_path.setText(job_dir + "/")
144       
145       list_of_files = os.listdir(job_dir)
146             
147       for i in range(0,len(list_of_files)):
148          tmp_file = job_dir + "/" + list_of_files[i]
149
150          if ( os.path.isdir(tmp_file) ):
151             self.list_jobs.addItem(str(list_of_files[i]))
152
153
154    # Update input and user code lists
155    def update_input(self):
156     
157       self.list_input.clear() 
158       self.list_user.clear()
159       self.push_copy.setEnabled(True)
160       self.push_create_set.setEnabled(True)
161     
162       job_to_show = job_dir + "/" + self.list_jobs.currentItem().text() + "/INPUT"
163
164       if ( os.path.isdir(job_to_show) ):
165
166          list_of_files = os.listdir(job_to_show)
167         
168          for i in range(0,len(list_of_files)):
169             tmp_file = job_to_show + "/" + list_of_files[i]
170             
171             if ( os.path.isfile(tmp_file) ):
172                self.list_input.addItem(str(list_of_files[i]))
173 
174       job_to_show = job_dir + "/" + self.list_jobs.currentItem().text() + "/USER_CODE"
175       
176       if ( os.path.isdir(job_to_show) ):
177         
178          list_of_files = os.listdir(job_to_show)
179         
180          for i in range(0,len(list_of_files)):
181             tmp_file = job_to_show + "/" + list_of_files[i]
182
183             if ( os.path.isfile(tmp_file) ):
184                self.list_user.addItem(str(list_of_files[i]))
185 
186 
187    # Make a copy of a job
188    def copy_job(self):
189 
190       self.setEnabled(False)
191       old_job_name = self.list_jobs.currentItem().text()
192       
193       text, ret = QtGui.QInputDialog.getText(self, "Copy job", "Enter new job name:", mode = QtGui.QLineEdit.Normal, text = old_job_name)
194       
195       if ( ret ):
196          new_job_name = str(text)
197       else:
198           self.setEnabled(True)
199           return
200         
201       new_input_dir  = job_dir + "/" + new_job_name + "/INPUT"
202
203#      check if a job exists with the new job name 
204       if ( os.path.isdir(new_input_dir) ):
205           notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
206           self.setEnabled(True)
207           return
208       else:
209           os.makedirs(new_input_dir)
210
211#      copy and rename input files (if present)       
212       job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
213
214       if ( os.path.isdir(job_to_copy) ):
215
216          list_of_files = os.listdir(job_to_copy)
217         
218          for i in range(0,len(list_of_files)):
219
220             tmp_file = job_to_copy + "/" + list_of_files[i]         
221             new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
222             shutil.copy(tmp_file, new_file)
223
224
225
226
227       new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
228       
229#      check if user code exists in the new job directory
230       if ( os.path.isdir(new_user_dir) ):
231           notify = QtGui.QMessageBox.warning(self,'Create new user code directory',"Error. Could not create user code directory. A user code directiory with the new name already exists.")
232           self.setEnabled(True)
233           return
234       else:
235           os.makedirs(new_user_dir)
236
237
238#      copy user code files (if present)       
239       user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
240
241       if ( os.path.isdir(user_to_copy) ):
242
243          list_of_files = os.listdir(user_to_copy)
244         
245          for i in range(0,len(list_of_files)):
246
247             tmp_file = user_to_copy + "/" + list_of_files[i]         
248             new_file = new_user_dir + "/" + list_of_files[i]
249             shutil.copy(tmp_file, new_file)
250
251       self.load_jobs()
252       self.list_input.clear() 
253       self.list_user.clear()
254       self.setEnabled(True)
255
256
257    # Create a whole set of jobs
258    def create_set(self):
259 
260       global set_list
261#      disable mainwindow 
262       self.setEnabled(False)
263     
264#      show Options Dialog     
265       opt = CreateSetBox()
266       opt.exec_()
267
268       old_job_name = self.list_jobs.currentItem().text()
269
270       for j in range(0,len(set_list)):
271
272          if ( set_list[j] != "" ):
273             new_job_name   = str(set_list[j])
274             new_input_dir  = job_dir + "/" + str(set_list[j]) + "/INPUT"
275          else:
276             continue
277
278#         check if a job exists with the new job name 
279          if ( os.path.isdir(new_input_dir) ):
280             notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
281             self.setEnabled(True)
282             return
283          else:
284             os.makedirs(new_input_dir)
285
286#         copy and rename input files (if present)       
287          job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
288
289          if ( os.path.isdir(job_to_copy) ):
290
291             list_of_files = os.listdir(job_to_copy)
292         
293             for i in range(0,len(list_of_files)):
294
295                tmp_file = job_to_copy + "/" + list_of_files[i]         
296                new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
297                shutil.copy(tmp_file, new_file)
298
299
300          new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
301       
302#         check if user code exists in the new job directory
303          if ( os.path.isdir(new_user_dir) ):
304              notify = QtGui.QMessageBox.warning(self,'Create new user code directory',"Error. Could not create user code directory. A user code directiory with the new name already exists.")
305              self.setEnabled(True)
306              return
307          else:
308              os.makedirs(new_user_dir)
309
310
311#         copy user code files (if present)       
312          user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
313
314          if ( os.path.isdir(user_to_copy) ):
315
316             list_of_files = os.listdir(user_to_copy)
317         
318             for i in range(0,len(list_of_files)):
319
320                tmp_file = user_to_copy + "/" + list_of_files[i]         
321                new_file = new_user_dir + "/" + list_of_files[i]
322                shutil.copy(tmp_file, new_file)
323
324          self.load_jobs()
325          self.list_input.clear() 
326          self.list_user.clear()
327
328       self.setEnabled(True) 
329   
330   
331 # Add a custom context menu
332    def openmenuinput(self, position):
333
334        menu = QtGui.QMenu()
335
336        selection = self.list_input.selectedItems()
337       
338        if ( len(selection) != 0 ):
339
340           openAction = menu.addAction('Open selected files')     
341           openAction.setStatusTip('Open file(s) in your favorite editor')
342           openAction.triggered.connect(self.OpenFilesInput)
343           action = menu.exec_(self.list_input.mapToGlobal(position))
344
345 # Add a custom context menu
346    def openmenuuser(self, position):
347
348        menu = QtGui.QMenu()
349
350        selection = self.list_user.selectedItems()
351       
352        if ( len(selection) != 0 ):
353
354           openAction = menu.addAction('Open selected files')     
355           openAction.setStatusTip('Open file(s) in your favorite editor')
356           openAction.triggered.connect(self.OpenFilesUser)
357           action = menu.exec_(self.list_user.mapToGlobal(position))
358
359
360    def OpenFilesInput(self):
361   
362       sel_job = self.list_jobs.currentItem().text()
363       sel_files = self.list_input.selectedItems()
364       
365       input_dir = job_dir + "/" + sel_job + "/INPUT/"
366       
367       open_files = ""
368       for i in range(0,len(sel_files)):
369          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text() + "; "
370
371       os.system(str(open_files))
372
373    def OpenFilesUser(self):
374   
375       sel_job = self.list_jobs.currentItem().text()
376       sel_files = self.list_user.selectedItems()
377       
378       input_dir = job_dir + "/" + sel_job + "/USER_CODE/"
379       
380       open_files = ""
381       for i in range(0,len(sel_files)):
382          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text() + "; "
383
384       os.system(str(open_files)) 
385       selection = self.list_jobs.selectedItems()
386 
387 
388 
389# Message box for showing RUN_CONTROL output
390class CreateSetBox(QtGui.QDialog):
391    def __init__(self):
392     
393        super(CreateSetBox, self).__init__()
394       
395        uic.loadUi(palm_bin + '/palm_jm_files/palm_jm_create_set.ui', self)
396       
397        self.show()
398       
399        return
400
401#   Cancel button
402    def rejected(self):
403     
404       self.close()
405     
406       return
407 
408
409#   OK button
410    def accept(self):
411     
412       global set_list
413       
414       text = self.list.toPlainText() 
415       set_list = text.split('\n')
416       self.close()
417     
418       return
419 
420# Main loop       
421def main():
422   
423    app = QtGui.QApplication(sys.argv)
424    res = JobManager() 
425    sys.exit(app.exec_())
426
427
428if __name__ == '__main__':
429    main()   
Note: See TracBrowser for help on using the repository browser.