Salome HOME
Adding test from srf2med conversion using MEDCoupling
[modules/hydrosolver.git] / src / HYDROGUI / HYDROSOLVERGUI.py
1 #  Copyright (C) 2012-2013 EDF
2 #
3 #  This file is part of SALOME HYDRO module.
4 #
5 #  SALOME HYDRO module is free software: you can redistribute it and/or modify
6 #  it under the terms of the GNU General Public License as published by
7 #  the Free Software Foundation, either version 3 of the License, or
8 #  (at your option) any later version.
9 #
10 #  SALOME HYDRO module is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with SALOME HYDRO module.  If not, see <http://www.gnu.org/licenses/>.
17
18 import sys
19 import os
20 import traceback
21 import logging
22
23 from PyQt5.QtWidgets import QMessageBox, QApplication, QDialog
24
25 import salome
26 import SALOME
27 import SalomePyQt
28 sgPyQt = SalomePyQt.SalomePyQt()
29 from salome.kernel.studyedit import getStudyEditor
30 from salome.kernel.logger import Logger
31 from salome.kernel import termcolor
32 logger = Logger("HYDROGUI", color = termcolor.BLUE)
33 #logger.setLevel(logging.ERROR)
34
35 import HYDROSOLVER_ORB
36
37 from salome.hydro.interpolz_gui import InterpolzDlg
38 from salome.hydro.assignStrickler_gui import assignStricklerDlg
39 from salome.hydro.changeCoordsDialog import changeCoordsDialog
40 from salome.hydro.gui_utils import HSGUIException, wait_cursor, \
41                                    get_and_check_selected_file_path
42 import salome.hydro.study as hydro_study
43 from salome.hydro.run_study.eficas.appli import EficasForRunStudyAppli
44 from salome.hydro.param_study.eficas.appli import EficasForParamStudyAppli
45 from salome.hydro.telma.eficas.appli import EficasForTelmaAppli
46 from salome.hydro.run_study.gui import create_case_study, \
47                                    run_selected_case_study, \
48                                    edit_selected_case_study, \
49                                    generate_job_for_selected_case_study
50 from eficasSalome import runEficas
51
52 from BndConditionsDialog import BoundaryConditionsDialog
53 from salome.hydro.initialFieldDialog import initialFieldDialog
54 from salome.hydro.checkBoundariesDialog import checkBoundariesDialog
55
56
57 ################################################
58 # GUI context class
59 # Used to store actions, menus, toolbars, etc...
60 ################################################
61
62 class GUIcontext:
63
64     # --- menus/toolbars/actions IDss
65
66     HYDRO_MENU_ID = 90
67     CREATE_STUDY_ID = 951
68     EDIT_STUDY_ID = 952
69     RUN_STUDY_ID = 953
70     GEN_STUDY_BATCH_ID = 954
71
72     CREATE_TELMA_CAS_ID = 955
73     EDIT_TELMA_CAS_ID = 956
74
75     GENERATE_INTERPOLZ_PY_ID = 957
76     GENERATE_ASSIGNSTRICKLER_PY_ID = 958
77
78     # TODO Add create and edit ?
79     EDIT_BOUNDARY_CONDITIONS_FILE_ID = 959
80     EDIT_INITIAL_FIELD_FILE_ID = 962
81
82     CREATE_PARAM_STUDY_ID = 963
83     EDIT_PARAM_STUDY_ID = 964
84     GEN_PARAM_STUDY_PYTHON_ID = 965
85     GEN_PARAM_STUDY_YACS_ID = 966
86
87     CHANGECOORDS_PY_ID = 967
88     CHECK_BOUNDARY_CONDITIONS_ID = 968
89
90     def __init__(self):
91         # create top-level menu
92         mid = sgPyQt.createMenu("Hydro", -1, GUIcontext.HYDRO_MENU_ID,
93                                 sgPyQt.defaultMenuGroup())
94         # create toolbar
95         tid = sgPyQt.createTool("Hydro")
96         # create actions and fill menu and toolbar with actions
97         act = sgPyQt.createAction(\
98                 GUIcontext.CHANGECOORDS_PY_ID,
99                 "Change coordinates",
100                 "Change coordinates",
101                 "Change mesh coordinates",
102                 "changes_coords.png")
103         sgPyQt.createMenu(act, mid)
104         sgPyQt.createTool(act, tid)
105
106         act = sgPyQt.createAction(\
107                 GUIcontext.GENERATE_INTERPOLZ_PY_ID,
108                 "Generate interpolz.py",
109                 "Generate interpolz.py",
110                 "Generate interpolation script for altitudes",
111                 "generate_interpolz_py.png")
112         sgPyQt.createMenu(act, mid)
113         sgPyQt.createTool(act, tid)
114
115         act = sgPyQt.createAction(\
116                 GUIcontext.GENERATE_ASSIGNSTRICKLER_PY_ID,
117                 "Generate assignStrickler.py",
118                 "Generate assignStrickler.py",
119                 "Generate assignation script for bottom friction coefficients",
120                  "assign_Strickler_py.png" )
121         sgPyQt.createMenu( act, mid )
122         sgPyQt.createTool( act, tid )
123
124         act = sgPyQt.createSeparator()
125
126         act = sgPyQt.createAction(\
127                 GUIcontext.EDIT_BOUNDARY_CONDITIONS_FILE_ID,
128                 "Edit boundary conditions file",
129                 "Edit boundary conditions file",
130                 "Create/edit the boundary conditions file for Telemac",
131                 "edit_boundary_conditions_file.png")
132         sgPyQt.createMenu(act, mid)
133         sgPyQt.createTool(act, tid)
134
135         act = sgPyQt.createAction(\
136                 GUIcontext.CHECK_BOUNDARY_CONDITIONS_ID,
137                 "Check boundary conditions",
138                 "Check boundary conditions",
139                 "display a graph with boundary conditions on the mesh",
140                 "check_boundary_conditions.png")
141         sgPyQt.createMenu(act, mid)
142         sgPyQt.createTool(act, tid)
143
144         act = sgPyQt.createAction(\
145                 GUIcontext.EDIT_INITIAL_FIELD_FILE_ID,
146                 "Edit initial field file",
147                 "Edit initial field file",
148                 "Create/edit the initial field file for Telemac",
149                 "edit_initial_field_file.png" )
150         sgPyQt.createMenu( act, mid )
151         sgPyQt.createTool( act, tid )
152
153         act = sgPyQt.createAction(\
154                 GUIcontext.CREATE_TELMA_CAS_ID,
155                 "Edit cas file (English)",
156                 "Edit cas file (English)",
157                 "Create/edit act .cas file for Telemac (English)",
158                 "create_telma_cas.png")
159         sgPyQt.createMenu(act, mid)
160         sgPyQt.createTool(act, tid)
161
162         act = sgPyQt.createAction(\
163                 GUIcontext.CREATE_STUDY_ID,
164                 "Execute a steering file",
165                 "Execute a steering file",
166                 "Fill formular for a normal execution",
167                 "create_study.png")
168
169         sgPyQt.createMenu(act, mid)
170         sgPyQt.createTool(act, tid)
171
172         act = sgPyQt.createAction(\
173                 GUIcontext.CREATE_PARAM_STUDY_ID,
174                 "Create Parameter Study",
175                 "Create Parameter Study",
176                 "Create act new Parameter Study",
177                 "create_param_study.png")
178         sgPyQt.createMenu(act, mid)
179         sgPyQt.createTool(act, tid)
180
181         act = sgPyQt.createSeparator()
182
183         # the following action are used in context popup
184
185         sgPyQt.createAction(\
186                 GUIcontext.EDIT_PARAM_STUDY_ID,
187                 "Edit param study",
188                 "Edit param study",
189                 "Edit study using python launcher")
190         sgPyQt.createAction(\
191                 GUIcontext.GEN_PARAM_STUDY_PYTHON_ID,
192                 "Generate Python script",
193                 "Generate Python script",
194                 "Generate act Python script from the eficas date")
195         sgPyQt.createAction(\
196                 GUIcontext.GEN_PARAM_STUDY_YACS_ID,
197                 "Generate YACS script",
198                 "Generate YACS script",
199                 "Generate act YACS script from the eficas date")
200
201         sgPyQt.createAction(\
202                 GUIcontext.RUN_STUDY_ID,
203                 "Compute study",
204                 "Compute study",
205                 "Compute study using python launcher")
206         sgPyQt.createAction(\
207                 GUIcontext.EDIT_STUDY_ID,
208                 "Edit study",
209                 "Edit study",
210                 "Edit the selected study")
211         sgPyQt.createAction(\
212                 GUIcontext.GEN_STUDY_BATCH_ID,
213                 "Generate batch job",
214                 "Generate batch job",
215                 "Generate a batch job to run the selected study")
216
217         sgPyQt.createAction(\
218                 GUIcontext.EDIT_TELMA_CAS_ID,
219                 "Edit Steering file",
220                 "Edit Steering file",
221                 "Edit a Telemac-Mascaret steering file")
222
223
224 ################################################
225 # Global variables
226 ################################################
227
228 # study-to-context map
229 __study2context__ = {}
230 # current context
231 __current_context__ = None
232 # object counter
233 __objectid__ = 0
234
235 ################################################
236 # Internal methods
237 ################################################
238
239 ###
240 # get active study ID
241 ###
242 #def _getStudyId():
243     #return sgPyQt.getStudyId()
244
245 ###
246 # get active study
247 ###
248 #def _getStudy():
249     #studyId = _getStudyId()
250     #study = getStudyManager().GetStudyByID(studyId)
251     #return study
252
253 ###
254 # returns True if object has children
255 ###
256 def _hasChildren(sobj):
257     if sobj:
258         study = salome.myStudy
259         iter  = study.NewChildIterator(sobj)
260         while iter.More():
261             name = iter.Value().GetName()
262             if name:
263                 return True
264             iter.Next()
265             pass
266         pass
267     return False
268
269 ###
270 # get current GUI context
271 ###
272 def _getContext():
273     global __current_context__
274     return __current_context__
275
276 ###
277 # set and return current GUI context
278 # study ID is passed as parameter
279 ###
280 def _setContext():
281     global __study2context__, __current_context__
282     #if studyID not in __study2context__:
283         #__study2context__[studyID] = GUIcontext()
284         #pass
285     #__current_context__ = __study2context__[studyID]
286     __current_context__ = GUIcontext()
287     return __current_context__
288
289 ###
290 # increment object counter in the map
291 ###
292 def _incObjToMap(m, id):
293     if id not in m: m[id] = 0
294     m[id] += 1
295     pass
296
297 ################################################
298 # Callback functions
299 ################################################
300
301 # called when module is activated
302 # returns True if activating is successfull and False otherwise
303 def activate():
304     ctx = _setContext()
305     return True
306
307 # called when module is deactivated
308 def deactivate():
309     pass
310
311 # called when active study is changed
312 # active study ID is passed as parameter
313 def activeStudyChanged():
314     ctx = _setContext()
315     pass
316
317 # called when popup menu is invoked
318 # popup menu and menu context are passed as parameters
319 def createPopupMenu(popup, context):
320     ed = getStudyEditor()
321     _setContext()
322     if salome.sg.SelectedCount() == 1:
323         # one object is selected
324         sobj = ed.study.FindObjectID(salome.sg.getSelected(0))
325         print("sobj: %s"%sobj) # strange bug with sobj is None when right clic on 3Dview in HYDROSOLVER used after HYDRO (generate AssignStrickler)
326         if sobj:
327             selectedType = ed.getTypeId(sobj)
328             if selectedType == hydro_study.TELMA_TYPE_ID:
329                 popup.addAction(sgPyQt.action(GUIcontext.EDIT_TELMA_CAS_ID))
330             elif selectedType == hydro_study.PARAM_STUDY_TYPE_ID:
331                 popup.addAction(sgPyQt.action(GUIcontext.EDIT_PARAM_STUDY_ID))
332                 popup.addAction(sgPyQt.action(GUIcontext.GEN_PARAM_STUDY_PYTHON_ID))
333                 popup.addAction(sgPyQt.action(GUIcontext.GEN_PARAM_STUDY_YACS_ID))
334             elif selectedType == hydro_study.STUDY_TYPE_ID:
335                 popup.addAction(sgPyQt.action(GUIcontext.EDIT_STUDY_ID))
336                 popup.addAction(sgPyQt.action(GUIcontext.RUN_STUDY_ID))
337                 popup.addAction(sgPyQt.action(GUIcontext.GEN_STUDY_BATCH_ID))
338
339 # called when GUI action is activated
340 # action ID is passed as parameter
341 def OnGUIEvent(commandID):
342     try:
343         dict_command[commandID]()
344     except HSGUIException as exc:
345         QMessageBox.critical(sgPyQt.getDesktop(),
346                                    QApplication.translate("OnGUIEvent", "Error"),
347                                    str(exc))
348     except:
349         logger.exception("Unhandled exception caught in HYDROSOLVER GUI")
350         msg = QApplication.translate("OnGUIEvent",
351             "Unhandled error happened in HYDROSOLVER module. Please report a bug on "
352             '<a href="https://forge-pleiade.der.edf.fr/projects/salome-rex/issues">SALOME bugtracker</a>, '
353             'category "HYDROSOLVER", describing how you got there and including the following traceback:')
354         msgBox = QMessageBox(QMessageBox.Critical,
355                                    QApplication.translate("OnGUIEvent", "Error"),
356                                    msg,
357                                    parent=sgPyQt.getDesktop())
358         msgBox.setDetailedText(traceback.format_exc())
359         msgBox.exec_()
360
361 ################################################
362 # GUI actions implementation
363 ################################################
364
365 ###
366 # Open Eficas for a new parametric study
367 ###
368 def create_param_study():
369     EficasForParamStudyAppli()
370 ###
371 # Open Eficas to edit a new parametric study
372 ###
373 def edit_param_study():
374     EficasForParamStudyAppli(get_and_check_selected_file_path())
375
376 ###
377 # Generate a python script from the eficas file
378 ###
379 def generate_param_study_python():
380     try:
381         with wait_cursor:
382             ed = hydro_study.HydroStudyEditor()
383             sobj = get_and_check_selected_file_path()
384             python_file = ed.generate_study_script(sobj)
385     except SALOME.SALOME_Exception as exc:
386         salome.sg.updateObjBrowser()
387         msg = str(QApplication.translate("generate_telemac2d_python",
388                       "An error happened while trying to generate telemac2d Python script:"))
389         msg += "\n" + exc.details.text
390         raise HSGUIException(msg)
391     QMessageBox.information(sgPyQt.getDesktop(),
392                             "Dumping done",
393                             "Generated Python script in:\n{}".format(python_file))
394
395 ###
396 # Generate a python script from the eficas file
397 ###
398 def generate_param_study_yacs():
399     try:
400         with wait_cursor:
401             ed = hydro_study.HydroStudyEditor()
402             sobj = get_and_check_selected_file_path()
403             yacs_file = ed.generate_study_yacs(sobj)
404     except SALOME.SALOME_Exception as exc:
405         salome.sg.updateObjBrowser()
406         msg = str(QApplication.translate("generate_telemac2d_yacs",
407                       "An error happened while trying to generate telemac2d Python script:"))
408         msg += "\n" + exc.details.text
409         raise HSGUIException(msg)
410     QMessageBox.information(sgPyQt.getDesktop(),
411                             "Dumping done",
412                             "Generated YACS scheme in:\n{}".format(yacs_file))
413
414 def open_schema_in_yacs():
415     ed = getStudyEditor()
416     sobj = ed.study.FindObjectID(salome.sg.getSelected(0))
417     filename = sobj.GetComment()
418     if filename.endswith(".comm"):
419         filename = filename[:-5] + ".xml"
420     if not os.path.isfile(filename):
421         raise HSGUIException(QApplication.translate("open_schema_in_yacs",
422                                   "Schema file %1 does not exist").arg(filename))
423     yg = salome.ImportComponentGUI("YACS")
424     yg.loadSchema(filename)
425
426 ###
427 # Open dialog for boundary conditions edition
428 ###
429 def edit_boundary_conditions_file():
430     desktop = sgPyQt.getDesktop()
431     dlg = BoundaryConditionsDialog(desktop)
432     dlg.exec_()
433
434 ###
435 # Open dialog for initial conditions edition
436 ###
437 def edit_initial_field_file():
438     desktop = sgPyQt.getDesktop()
439     dlg = initialFieldDialog(desktop)
440     dlg.exec_()
441
442 ###
443 # Open dialog for initial conditions edition
444 ###
445 def check_boundaries():
446     desktop = sgPyQt.getDesktop()
447     dlg = checkBoundariesDialog(desktop)
448     dlg.exec_()
449
450 ###
451 # Open dialog for interpolz.py script generation
452 ###
453 def generate_interpolz_py():
454     desktop = sgPyQt.getDesktop()
455     dlg = InterpolzDlg(desktop)
456     dlg.show()
457
458 ###
459 # Open dialog for assignStrickler.py script generation
460 ###
461 def generate_assignStrickler_py():
462     desktop = sgPyQt.getDesktop()
463     dlg = assignStricklerDlg(desktop)
464     dlg.show()
465
466 def changeCoords_py():
467     desktop = sgPyQt.getDesktop()
468     dlg = changeCoordsDialog(desktop)
469     dlg.exec_()
470
471 ###
472 # Open dialog for boundary conditions edition
473 ###
474 def generate_interpolks_py():
475     QMessageBox.warning(sgPyQt.getDesktop(),
476                         "",
477                         "Generation of interpolks.py not implemented yet")
478     return
479
480 ###
481 # Open dialog for creation of steering file
482 ###
483 def create_telma_cas():
484     EficasForTelmaAppli(code='TELEMAC', lang='en')
485
486 ###
487 # Open dialog for edition of steering file
488 ###
489 def edit_telma_cas():
490     # TODO: See how to detect module
491     EficasForTelmaAppli(fichier=get_and_check_selected_file_path(),
492                         code='TELEMAC', lang='en')
493
494 ###
495 # Commands dictionary
496 ###
497 dict_command = {
498     GUIcontext.CREATE_STUDY_ID: create_case_study,
499     GUIcontext.EDIT_STUDY_ID: edit_selected_case_study,
500     GUIcontext.RUN_STUDY_ID: run_selected_case_study,
501     GUIcontext.GEN_STUDY_BATCH_ID: generate_job_for_selected_case_study,
502     GUIcontext.CREATE_TELMA_CAS_ID: create_telma_cas,
503     GUIcontext.EDIT_TELMA_CAS_ID: edit_telma_cas,
504     GUIcontext.GENERATE_INTERPOLZ_PY_ID: generate_interpolz_py,
505     GUIcontext.GENERATE_ASSIGNSTRICKLER_PY_ID: generate_assignStrickler_py,
506     GUIcontext.CHANGECOORDS_PY_ID: changeCoords_py,
507     GUIcontext.EDIT_BOUNDARY_CONDITIONS_FILE_ID: edit_boundary_conditions_file,
508     GUIcontext.CHECK_BOUNDARY_CONDITIONS_ID: check_boundaries,
509     GUIcontext.EDIT_INITIAL_FIELD_FILE_ID: edit_initial_field_file,
510     GUIcontext.CREATE_PARAM_STUDY_ID: create_param_study,
511     GUIcontext.EDIT_PARAM_STUDY_ID: edit_param_study,
512     GUIcontext.GEN_PARAM_STUDY_PYTHON_ID: generate_param_study_python,
513     GUIcontext.GEN_PARAM_STUDY_YACS_ID: generate_param_study_yacs,
514     }