source: palm/trunk/SCRIPTS/palm_jm @ 2488

Last change on this file since 2488 was 2484, checked in by maronga, 7 years ago

updates in palm_jm and palmrungui

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