source: palm/trunk/SCRIPTS/palm_jm @ 2728

Last change on this file since 2728 was 2718, checked in by maronga, 7 years ago

deleting of deprecated files; headers updated where needed

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