Salome HOME
[MEDCalc]: replace mode now targets the current view only.
[modules/med.git] / src / MEDCalc / cmp / MEDPresentation.cxx
1 // Copyright (C) 2011-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Authors: A Bruneton (CEA), C Aguerre (EdF)
20
21 #include "MEDFactoryClient.hxx"
22 #include "MEDPresentation.hxx"
23 #include "MEDPresentationException.hxx"
24 #include "MEDCouplingRefCountObject.hxx"
25 #include <SALOME_KernelServices.hxx>
26 #undef LOG
27 #include <Basics_Utils.hxx>
28 #include <PyInterp_Utils.h>
29
30 #include <sstream>
31
32 const std::string MEDPresentation::PROP_NAME  = "name";
33 const std::string MEDPresentation::PROP_NB_COMPONENTS = "nbComponents";
34 const std::string MEDPresentation::PROP_SELECTED_COMPONENT = "selectedComponent";
35 const std::string MEDPresentation::PROP_COMPONENT = "component_";
36 const std::string MEDPresentation::PROP_COLOR_MAP = "colorMap";
37 const std::string MEDPresentation::PROP_SCALAR_BAR_RANGE = "scalarBarRange";
38
39 MEDPresentation::MEDPresentation(MEDPresentation::TypeID fieldHandlerId, const std::string& name,
40                                  const MEDCALC::MEDPresentationViewMode viewMode,
41                                  const MEDCALC::MEDPresentationColorMap colorMap,
42                                  const MEDCALC::MEDPresentationScalarBarRange sbRange)
43     : _fieldHandlerId(fieldHandlerId), _propertiesStr(),
44       //_pipeline(0), _display(0)
45       _selectedComponentIndex(-1),
46       _viewMode(viewMode),
47       _colorMap(colorMap),
48       _sbRange(sbRange),
49       _renderViewPyId(-1),  // will be set by getRenderViewCommand()
50       _objId(GeneratePythonId()),
51       _dispId(_objId), _lutId(_objId),
52       _globalDict(0)
53 {
54   MEDCALC::MEDDataManager_ptr dataManager(MEDFactoryClient::getDataManager());
55   MEDCALC::FieldHandler* fieldHandler = dataManager->getFieldHandler(fieldHandlerId);
56   MEDCALC::MeshHandler* meshHandler = dataManager->getMesh(fieldHandler->meshid);
57   MEDCALC::DatasourceHandler* dataSHandler = dataManager->getDatasourceHandlerFromID(meshHandler->sourceid);
58
59   _fileName = dataSHandler->uri;
60   _fieldName = fieldHandler->fieldname;
61   _fieldType = getFieldTypeString((MEDCoupling::TypeOfField) fieldHandler->type);
62
63   if (_fileName.substr(0, 7) != std::string("file://")) {
64     const char* msg = "MEDPresentation(): Data source is not a file! Can not proceed.";
65     STDLOG(msg);
66     throw MEDPresentationException(msg);
67   }
68   _fileName = _fileName.substr(7, _fileName.size());
69
70   setStringProperty(MEDPresentation::PROP_NAME, name);
71
72   setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, 0);
73   setIntProperty(MEDPresentation::PROP_SELECTED_COMPONENT, 0);
74
75   setIntProperty(MEDPresentation::PROP_COLOR_MAP, static_cast<int>(MEDCALC::COLOR_MAP_DEFAULT));
76   setIntProperty(MEDPresentation::PROP_SCALAR_BAR_RANGE, static_cast<int>(MEDCALC::SCALAR_BAR_RANGE_DEFAULT));
77 }
78
79 MEDPresentation::~MEDPresentation()
80 {
81   STDLOG("~MEDPresentation(): clear display");
82   {
83     PyLockWrapper lock;
84     std::ostringstream oss_o, oss_v, oss;
85     oss_o << "__obj" << _objId;
86     oss_v << "__view" << _renderViewPyId;
87     oss << "pvs.Hide(" << oss_o.str() <<  ", view=" << oss_v.str() << ");";
88     oss << "pvs.Render();";
89
90     PyRun_SimpleString(oss.str().c_str());
91   }
92 }
93
94 void
95 MEDPresentation::generatePipeline()
96 {
97   // Might be more complicated in the future:
98
99   this->internalGeneratePipeline();
100 }
101
102 //void
103 //MEDPresentation::pushPyObjects(PyObjectId obj, PyObjectId disp)
104 //{
105 //  _pipeline.push_back(obj);
106 //  _display.push_back(disp);
107 //}
108
109 void
110 MEDPresentation::pushAndExecPyLine(const std::string & lin)
111 {
112   execPyLine(lin);
113   _pythonCmds.push_back(lin);
114 }
115
116 void
117 MEDPresentation::execPyLine(const std::string & lin)
118 {
119   PyLockWrapper lock;
120 //  STDLOG("@@@@ MEDPresentation::execPyLine() about to exec >> " << lin);
121   if(PyRun_SimpleString(lin.c_str()))
122     {
123       std::ostringstream oss;
124       oss << "MEDPresentation::execPyLine(): following Python command failed!\n";
125       oss << ">> " << lin;
126       STDLOG(oss.str());
127       throw KERNEL::createSalomeException(oss.str().c_str());
128     }
129
130 }
131
132 void
133 MEDPresentation::setStringProperty(const std::string& propName, const std::string& propValue)
134 {
135   _propertiesStr[propName] = propValue;
136 }
137
138 const std::string
139 MEDPresentation::getStringProperty(const std::string& propName) const
140 {
141   std::map<std::string, std::string>::const_iterator it = _propertiesStr.find(propName);
142   if (it != _propertiesStr.end()) {
143       return (*it).second;
144   }
145   else {
146       STDLOG("MEDPresentation::getStringProperty(): no property named " + propName);
147       throw MEDPresentationException("MEDPresentation::getStringProperty(): no property named " + propName);
148   }
149 }
150
151 void
152 MEDPresentation::setIntProperty(const std::string& propName, const int propValue)
153 {
154   _propertiesInt[propName] = propValue;
155 }
156
157 int
158 MEDPresentation::getIntProperty(const std::string& propName) const
159 {
160   std::map<std::string, int>::const_iterator it = _propertiesInt.find(propName);
161   if (it != _propertiesInt.end()) {
162       return (*it).second;
163   }
164   else {
165       STDLOG("MEDPresentation::getIntProperty(): no property named " + propName);
166       throw MEDPresentationException("MEDPresentation::getIntProperty(): no property named " + propName);
167   }
168 }
169
170  void
171  MEDPresentation::dumpIntProperties() const
172  {
173    std::map<std::string, int>::const_iterator it = _propertiesInt.begin();
174    STDLOG("@@@ Dumping INT properties");
175    for(; it != _propertiesInt.end(); ++it)
176      {
177        std::ostringstream oss;
178        oss << (*it).first << "  ->   " << (*it).second;
179        STDLOG(oss.str());
180      }
181  }
182
183  void
184  MEDPresentation::dumpStringProperties() const
185  {
186    std::map<std::string, std::string>::const_iterator it = _propertiesStr.begin();
187    STDLOG("@@@ Dumping STR properties");
188    for(; it != _propertiesStr.end(); ++it)
189      {
190        std::ostringstream oss;
191        oss << (*it).first << "  ->   " << (*it).second;
192        STDLOG(oss.str());
193      }
194  }
195
196  void
197  MEDPresentation::internalGeneratePipeline()
198  {
199    PyLockWrapper lock;
200    pushAndExecPyLine( "import pvsimple as pvs;");
201  }
202
203
204 PyObject*
205 MEDPresentation::getPythonObjectFromMain(const char* python_var) const
206 {
207   if (! _globalDict)
208     {
209       // All the calls below returns *borrowed* references
210       PyObject* main_module = PyImport_AddModule((char*)"__main__");
211       _globalDict = PyModule_GetDict(main_module);
212     }
213   return PyDict_GetItemString(_globalDict, python_var);
214 }
215
216 std::string
217 MEDPresentation::getFieldTypeString(MEDCoupling::TypeOfField fieldType) const
218 {
219   switch(fieldType)
220   {
221     case MEDCoupling::ON_CELLS:
222       return "CELLS";
223     case MEDCoupling::ON_NODES:
224       return "POINTS";
225     default:
226       STDLOG("MEDPresentation::getFieldTypeString() -- Not implemented ! Gauss points?");
227       return "";
228   }
229 }
230
231 std::string
232 MEDPresentation::getRenderViewCommand() const
233 {
234   std::ostringstream oss, oss2;
235
236   oss << "__view" << _renderViewPyId;
237   std::string view(oss.str());
238   oss2 << "pvs._DisableFirstRenderCameraReset();" << std::endl;
239   if (_viewMode == MEDCALC::VIEW_MODE_OVERLAP) {
240       // this might potentially re-assign to an existing view variable, but this is OK, we
241       // normally reassign exaclty the same RenderView object.
242       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');" << std::endl;
243   } else if (_viewMode == MEDCALC::VIEW_MODE_REPLACE) {
244       // same as above
245       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');" << std::endl;
246       oss2 << "pvs.active_objects.source and pvs.Hide(view=" << view << ");" << std::endl;
247       oss2 << "pvs.Render();" << std::endl;
248   } else if (_viewMode == MEDCALC::VIEW_MODE_NEW_LAYOUT) {
249       oss2 <<  "__layout1 = pvs.servermanager.misc.ViewLayout(registrationGroup='layouts');" << std::endl;
250       oss2 << view << " = pvs.CreateView('RenderView');" << std::endl;
251   } else if (_viewMode == MEDCALC::VIEW_MODE_SPLIT_VIEW) {
252       oss2 << view << " = pvs.CreateView('RenderView');" << std::endl;
253   }
254   return oss2.str();
255 }
256
257 std::string
258 MEDPresentation::getResetCameraCommand() const
259 {
260   std::ostringstream oss;
261   oss << "__view" << _renderViewPyId << ".ResetCamera();";
262   return oss.str();
263 }
264
265 std::string
266 MEDPresentation::getComponentSelectionCommand() const
267 {
268   std::ostringstream oss, oss_l;
269   oss_l << "__lut" << _lutId;    std::string lut(oss_l.str());
270
271   if (_selectedComponentIndex != -1)
272     {
273       oss << lut << ".VectorMode = 'Component';\n";
274       oss << lut << ".VectorComponent = " << _selectedComponentIndex << ";";
275     }
276   else  // Euclidean norm
277     {
278       oss << lut << ".VectorMode = 'Magnitude';";
279     }
280   return oss.str();
281 }
282
283 std::string
284 MEDPresentation::getColorMapCommand() const
285 {
286   std::ostringstream oss, oss_l;
287   oss_l << "__lut" << _lutId;    std::string lut(oss_l.str());
288   switch (_colorMap) {
289   case MEDCALC::COLOR_MAP_BLUE_TO_RED_RAINBOW:
290     oss << lut << ".ApplyPreset('Blue to Red Rainbow',True);";
291     break;
292   case MEDCALC::COLOR_MAP_COOL_TO_WARM:
293     oss << lut << ".ApplyPreset('Cool to Warm',True);";
294     break;
295   default:
296     STDLOG("MEDPresentation::getColorMapCommand(): invalid colormap!");
297     throw KERNEL::createSalomeException("MEDPresentation::getColorMapCommand(): invalid colormap!");
298   }
299   return oss.str();
300 }
301 std::string
302 MEDPresentation::getRescaleCommand() const
303 {
304   std::ostringstream oss, oss_d;
305   oss_d << "__disp" << _dispId;    std::string disp(oss_d.str());
306   switch(_sbRange)
307   {
308     case MEDCALC::SCALAR_BAR_ALL_TIMESTEPS:
309       oss << disp <<  ".RescaleTransferFunctionToDataRangeOverTime();";
310       break;
311     case MEDCALC::SCALAR_BAR_CURRENT_TIMESTEP:
312       oss << disp <<  ".RescaleTransferFunctionToDataRange(False);";
313       break;
314     default:
315       STDLOG("MEDPresentation::getRescaleCommand(): invalid range!");
316       throw KERNEL::createSalomeException("MEDPresentation::getRescaleCommand(): invalid range!");
317   }
318   return oss.str();
319 }
320
321 int
322 MEDPresentation::GeneratePythonId()
323 {
324   static int INIT_ID = 0;
325   return INIT_ID++;
326 }
327
328 void
329 MEDPresentation::activateView()
330 {
331   PyLockWrapper lock;
332
333   std::ostringstream oss;
334   oss << "pvs.SetActiveView(__view" << _renderViewPyId << ");";
335   pushAndExecPyLine(oss.str());
336 }
337
338
339 std::string
340 MEDPresentation::paravisDump() const
341 {
342   using namespace std;
343   ostringstream oss;
344   for (vector<string>::const_iterator it=_pythonCmds.begin(); it != _pythonCmds.end(); ++it)
345     {
346       oss << (*it);
347       oss << "\n";
348     }
349   return oss.str();
350 }
351
352 /**
353  * Query all available component names for the field associated with this presentation.
354  * Fills in all the corresponding string properties:
355  *  - PROP_COMPONENT1
356  *  - PROP_COMPONENT2
357  *    etc...
358  *  and the number of components.
359  */
360 void
361 MEDPresentation::fillAvailableFieldComponents()
362 {
363   PyLockWrapper lock;  // GIL!
364
365   std::ostringstream oss_o;
366   oss_o << "__obj" << _objId;      std::string obj(oss_o.str());
367   std::string typ;
368
369   if(_fieldType == "CELLS") {
370       typ = "CellData";
371   }
372   else if (_fieldType == "POINTS") {
373       typ = "PointData";
374   }
375   else {
376       std::string msg("Unsupported spatial discretisation: " + _fieldType);
377       STDLOG(msg);
378       throw KERNEL::createSalomeException(msg.c_str());
379   }
380
381   std::ostringstream oss;
382   oss << "__nbCompo = " << obj << "." << typ << ".GetArray('" <<  _fieldName << "').GetNumberOfComponents();";
383   execPyLine(oss.str());
384   PyObject* p_obj = getPythonObjectFromMain("__nbCompo");
385   long nbCompo;
386   if (p_obj && PyInt_Check(p_obj))
387     nbCompo = PyInt_AS_LONG(p_obj);
388   else
389     {
390       STDLOG("Unexpected Python error");
391       throw KERNEL::createSalomeException("Unexpected Python error");
392     }
393   setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, nbCompo);
394   for (long i = 0; i<nbCompo; i++)
395     {
396       std::ostringstream oss2;
397       oss2 << "__compo = " << obj << "." << typ << ".GetArray('" <<  _fieldName << "').GetComponentName(" << i << ");";
398       execPyLine(oss2.str());
399       PyObject* p_obj = getPythonObjectFromMain("__compo");
400       std::string compo;
401       if (p_obj && PyString_Check(p_obj))
402         compo = std::string(PyString_AsString(p_obj));  // pointing to internal Python memory, so make a copy!!
403       else
404         {
405           STDLOG("Unexpected Python error");
406           throw KERNEL::createSalomeException("Unexpected Python error");
407         }
408       std::ostringstream oss_p;
409       oss_p << MEDPresentation::PROP_COMPONENT << i;
410       setStringProperty(oss_p.str(), compo);
411     }
412 }
413