source: palm/trunk/SCRIPTS/palm_jm @ 2714

Last change on this file since 2714 was 2696, checked in by kanani, 6 years ago

Merge of branch palm4u into trunk

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