import threading
import inspect
import traceback
-import re
import copy
import salome
from SALOME_ComponentPy import SALOME_ComponentPy_i
from SALOME_DriverPy import SALOME_DriverPy_i
import SALOMERuntime
-import loader
import pilot
from salome.kernel.logger import Logger
logger = Logger("PARAMETRIC", color = termcolor.BLUE)
logger.setLevel(logging.DEBUG)
-from salome.parametric import ParametricStudyEditor, ParametricStudy
+from salome.parametric import ParametricStudyEditor, ParametricStudy, parse_entry
start_script = """
from salome.kernel.parametric.pyscript_utils import \
self.salome_runtime.addCatalog(self.session_catalog)
return self.salome_runtime
- def _parse_entry(self, selected_value):
- """
- Find entry if selected_value is something like "name (entry)"
- """
- entry = selected_value
- match = re.search("\((.*)\)$", entry)
- if match is not None:
- entry = match.group(1)
- return entry
-
def RunStudy(self, studyId, caseEntry):
try:
self.beginService("PARAMETRIC.RunStudy")
init_solver = solver_compo_def._serviceMap["Init"].clone(None)
init_solver.setComponent(solver_compo_inst)
init_solver.getInputPort("studyID").edInit(studyId)
- entry = self._parse_entry(param_study.solver_case_entry)
+ entry = parse_entry(param_study.solver_case_entry)
init_solver.getInputPort("detCaseEntry").edInit(entry)
foreach.edSetInitNode(init_solver)
#logger.setLevel(logging.ERROR)
import PARAMETRIC
-from salome.parametric.gui import MainPanel
+from salome.parametric.gui import MainPanel, GenJobDialog
from salome.parametric import ParametricStudyEditor
################################################
class GUIcontext:
# menus/toolbars/actions IDs
- PARAMETRIC_MENU = 0
- CREATE_PARAMETRIC_STUDY = 1
- RUN_PARAMETRIC_STUDY = 2
- EXPORT_DATA_TO_CSV = 3
- EDIT_PARAMETRIC_STUDY = 4
+ PARAMETRIC_MENU = 8950
+ CREATE_PARAMETRIC_STUDY = 8951
+ RUN_PARAMETRIC_STUDY = 8952
+ EXPORT_DATA_TO_CSV = 8953
+ EDIT_PARAMETRIC_STUDY = 8954
+ GENERATE_JOB = 8955
# constructor
def __init__( self ):
"Edit the selected parametric study",
"edit_param_study.png")
+ sgPyQt.createAction(GUIcontext.GENERATE_JOB,
+ "Generate batch job",
+ "Generate batch job",
+ "Generate a batch job to run the selected parametric study",
+ "generate_job.png")
+
################################################
# Global variables
################################################
if selectedType == salome.parametric.study.PARAM_STUDY_TYPE_ID:
popup.addAction(sgPyQt.action(GUIcontext.EDIT_PARAMETRIC_STUDY))
popup.addAction(sgPyQt.action(GUIcontext.RUN_PARAMETRIC_STUDY))
+ popup.addAction(sgPyQt.action(GUIcontext.GENERATE_JOB))
popup.addAction(sgPyQt.action(GUIcontext.EXPORT_DATA_TO_CSV))
# process GUI action
panel.new_study()
def edit_study():
- study_id = sgPyQt.getStudyId()
entry = salome.sg.getSelected(0)
- ed = ParametricStudyEditor(study_id)
+ ed = ParametricStudyEditor()
panel = MainPanel()
panel.edit_study(ed.get_parametric_study(entry))
qapp.translate("export_to_csv", "Error"),
qapp.translate("export_to_csv", "Export to CSV file failed: %s" % exc))
+def generate_job():
+ entry = salome.sg.getSelected(0)
+ ed = ParametricStudyEditor()
+ dialog = GenJobDialog(sgPyQt.getDesktop(), ed.get_parametric_study(entry))
+ dialog.exec_()
+
# ----------------------- #
dict_command = {
GUIcontext.CREATE_PARAMETRIC_STUDY: new_study,
GUIcontext.RUN_PARAMETRIC_STUDY: run_study,
GUIcontext.EXPORT_DATA_TO_CSV: export_to_csv,
- GUIcontext.EDIT_PARAMETRIC_STUDY: edit_study
+ GUIcontext.EDIT_PARAMETRIC_STUDY: edit_study,
+ GUIcontext.GENERATE_JOB: generate_job
}
# along with SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
import study
+import genjob
ParametricStudy = study.ParametricStudy
ParametricVariable = study.ParametricVariable
ParametricStudyEditor = study.ParametricStudyEditor
+generate_job = genjob.generate_job
+parse_entry = genjob.parse_entry
--- /dev/null
+# Copyright (C) 2012 EDF
+#
+# This file is part of SALOME PARAMETRIC module.
+#
+# SALOME PARAMETRIC module 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 3 of the License, or
+# (at your option) any later version.
+#
+# SALOME PARAMETRIC module 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 SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import tempfile
+from datetime import datetime
+
+import salome
+from salome.kernel.studyedit import getStudyEditor
+from study import ParametricStudy
+
+job_script_template = """
+#!/usr/bin/env python
+
+import salome
+import PARAMETRIC
+
+salome.salome_init()
+
+# load study
+study = salome.myStudyManager.Open("%(input_study)s")
+
+# start container and load PARAMETRIC component
+comp = salome.lcc.FindOrLoadComponent("ParametricContainer", "PARAMETRIC")
+
+# run parametric study
+comp.RunStudy(study._get_StudyId(), "%(param_entry)s")
+
+# save study
+salome.myStudyManager.SaveAs("%(output_study)s", study, False)
+"""
+
+def generate_job(param_study, result_study_file_name, result_dir, resource):
+ """
+ Create a Launcher job using the parameters specified by the user.
+ """
+ # Save Salome study
+ ed = getStudyEditor()
+ name_wo_space = param_study.name.replace(" ", "_")
+ (fd, input_study) = tempfile.mkstemp(prefix = name_wo_space + "_Input_", suffix = ".hdf")
+ os.close(fd)
+ salome.myStudyManager.SaveAs(input_study, ed.study, False)
+
+ # Generate job script
+ job_script = job_script_template % {"input_study": os.path.basename(input_study),
+ "param_entry": param_study.entry,
+ "output_study": result_study_file_name}
+ (fd, job_script_file) = tempfile.mkstemp(prefix = "job_" + name_wo_space + "_", suffix = ".py")
+ os.close(fd)
+ f = open(job_script_file, "w")
+ f.write(job_script)
+ f.close()
+
+ # Define job parameters
+ job_params = salome.JobParameters()
+ job_params.job_name = name_wo_space
+ job_params.job_type = "python_salome"
+ job_params.job_file = job_script_file
+ job_params.in_files = [input_study]
+ job_params.out_files = [result_study_file_name]
+ job_params.result_directory = result_dir
+
+ # Add files to transfer from the computation code
+ if param_study.solver_code_type == ParametricStudy.SALOME_COMPONENT:
+ code = param_study.salome_component_name
+ comp = salome.lcc.FindOrLoadComponent("FactoryServer", code)
+ if comp is not None and hasattr(comp, "GetFilesToTransfer"):
+ (code_in_files, code_out_files) = comp.GetFilesToTransfer(ed.studyId,
+ parse_entry(param_study.solver_case_entry))
+ job_params.in_files += code_in_files
+ job_params.out_files += code_out_files
+
+ # Define resource parameters
+ job_params.resource_required = salome.ResourceParameters()
+ job_params.resource_required.name = resource
+ job_params.resource_required.nb_proc = param_study.nb_parallel_computations + 1
+
+ # Generate name for the working directory
+ res_manager = salome.naming_service.Resolve("/ResourcesManager")
+ res_definition = res_manager.GetResourceDefinition(resource)
+ res_work_dir = res_definition.working_directory
+ if res_work_dir != "":
+ timestr = datetime.now().ctime()
+ timestr = timestr.replace('/', '_')
+ timestr = timestr.replace('-', '_')
+ timestr = timestr.replace(':', '_')
+ timestr = timestr.replace(' ', '_')
+ work_dir = res_work_dir + "/" + job_params.job_name + "_" + timestr
+ job_params.work_directory = work_dir
+
+ # Create Launcher job
+ launcher = salome.naming_service.Resolve('/SalomeLauncher')
+ launcher.createJob(job_params)
+
+def parse_entry(selected_value):
+ """
+ Find entry if selected_value is something like "name (entry)"
+ """
+ entry = selected_value
+ match = re.search("\((.*)\)$", entry)
+ if match is not None:
+ entry = match.group(1)
+ return entry
# You should have received a copy of the GNU Lesser General Public License
# along with SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
-SET(PYUIC_FILES wizard_ui.py varrange_ui.py execparams_ui.py)
+SET(PYUIC_FILES wizard_ui.py varrange_ui.py execparams_ui.py genjob_ui.py)
SET(INSTALL_DIR ${PYTHONDIR}/salome/parametric/gui)
FOREACH(OUTPUT ${PYUIC_FILES})
# along with SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
import mainpanel
+import genjob
MainPanel = mainpanel.MainPanel
+GenJobDialog = genjob.GenJobDialog
--- /dev/null
+# Copyright (C) 2012 EDF
+#
+# This file is part of SALOME PARAMETRIC module.
+#
+# SALOME PARAMETRIC module 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 3 of the License, or
+# (at your option) any later version.
+#
+# SALOME PARAMETRIC module 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 SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+from PyQt4 import QtGui, QtCore
+
+import salome
+from salome.parametric import generate_job
+from genjob_ui import Ui_GenJobDialog
+
+
+class GenJobDialog(QtGui.QDialog, Ui_GenJobDialog):
+
+ def __init__(self, parent, param_study):
+ QtGui.QDialog.__init__(self, parent)
+ self.setupUi(self)
+ self.connect(self.dialogButtonBox, QtCore.SIGNAL("accepted()"), self.validate)
+ self.connect(self.dialogButtonBox, QtCore.SIGNAL("rejected()"), self.close)
+ self.connect(self.chooseResultDirectoryButton, QtCore.SIGNAL("clicked()"), self.choose_result_dir)
+ self.resultStudyLE.setText(param_study.name.replace(" ", "_") + "_Result.hdf")
+ self.resultDirectoryLE.setText(os.getcwd())
+
+ # Populate resource combo box
+ res_manager = salome.naming_service.Resolve("/ResourcesManager")
+ res_params = salome.ResourceParameters()
+ res_list = res_manager.GetFittingResources(res_params)
+ self.resourceCB.addItems(res_list)
+
+ self.param_study = param_study
+
+ def choose_result_dir(self):
+ directory = QtGui.QFileDialog.getExistingDirectory(self,
+ directory = self.resultDirectoryLE.text(),
+ options = QtGui.QFileDialog.ShowDirsOnly)
+ if not directory.isNull():
+ self.resultDirectoryLE.setText(directory)
+
+ def validate(self):
+ generate_job(self.param_study, str(self.resultStudyLE.text()),
+ str(self.resultDirectoryLE.text()), str(self.resourceCB.currentText()))
+ self.close()
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GenJobDialog</class>
+ <widget class="QDialog" name="GenJobDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>636</width>
+ <height>202</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Generate Job</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Result Study Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="resultStudyLE"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Result Directory:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="resultDirectoryLE">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="chooseResultDirectoryButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Resource</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="resourceCB"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>43</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="dialogButtonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>