Salome HOME
5284d0387a2c8d81a8e2427d1ad84818346cf668
[modules/med.git] / src / MEDCalc / cmp / MEDPresentation.cxx
1 // Copyright (C) 2011-2020  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
20 // Authors: A Bruneton (CEA), C Aguerre (EdF)
21
22 #include "MEDPyLockWrapper.hxx"
23 #include "MEDFactoryClient.hxx"
24 #include "MEDPresentation.hxx"
25 #include "MEDPresentationException.hxx"
26 #include "MEDCouplingRefCountObject.hxx"
27 #include <SALOME_KernelServices.hxx>
28 #undef LOG
29 #include <Basics_Utils.hxx>
30
31 #include <sstream>
32
33 #if PY_VERSION_HEX < 0x03050000
34 static char*
35 Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
36 {
37         return _Py_wchar2char(text, error_pos);
38 }
39 #endif
40
41 const std::string MEDPresentation::PROP_NAME  = "name";
42 const std::string MEDPresentation::PROP_NB_COMPONENTS = "nbComponents";
43 const std::string MEDPresentation::PROP_SELECTED_COMPONENT = "selectedComponent";
44 const std::string MEDPresentation::PROP_COMPONENT = "component_";
45 const std::string MEDPresentation::PROP_COLOR_MAP = "colorMap";
46 const std::string MEDPresentation::PROP_SCALAR_BAR_RANGE = "scalarBarRange";
47
48 MEDPresentation::MEDPresentation(MEDPresentation::TypeID handlerId, const std::string& name,
49                                  const MEDCALC::ViewModeType viewMode,
50                                  const MEDCALC::ColorMapType colorMap,
51                                  const MEDCALC::ScalarBarRangeType sbRange)
52     : _handlerId(handlerId), _propertiesStr(),
53       _mcFieldType(MEDCoupling::ON_CELLS),
54       _pvFieldType(""), _meshName(""), _fieldName(""), _fileName(""),
55       _selectedComponentIndex(-1),
56       _viewMode(viewMode),
57       _colorMap(colorMap),
58       _sbRange(sbRange),
59       _renderViewPyId(-1),  // will be set by MEDPresentationManager_i::_makePresentation()
60       _globalDict(0)
61 {
62   setStringProperty(MEDPresentation::PROP_NAME, name);
63
64   setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, 0);
65   setIntProperty(MEDPresentation::PROP_SELECTED_COMPONENT, 0);
66
67   setIntProperty(MEDPresentation::PROP_COLOR_MAP, static_cast<int>(colorMap));
68   setIntProperty(MEDPresentation::PROP_SCALAR_BAR_RANGE, static_cast<int>(sbRange));
69
70   // Python variables:
71   int id = GeneratePythonId();
72   std::ostringstream oss_o, oss_d, oss_l, oss_s, oss_r;
73   oss_o << "__obj" << id;
74   oss_s << "__srcObj" << id;
75   oss_d << "__disp" << id;
76   oss_l << "__lut" << id;
77   oss_r << "__range" << id;
78   _objVar = oss_o.str();
79   _srcObjVar = oss_s.str();
80   _dispVar = oss_d.str();
81   _lutVar = oss_l.str();
82   _rangeVar = oss_r.str();
83 }
84
85 /**
86  * For most of the presentations the field name etc is required.
87  * For the MEDPresentationMeshView however, the handler ID is a mesh handler ID, not a field, and the
88  * treatment is specific.
89  */
90 void
91 MEDPresentation::initFieldMeshInfos()
92 {
93   MEDCALC::MEDDataManager_ptr dataManager(MEDFactoryClient::getDataManager());
94   MEDCALC::FieldHandler* fieldHandler = dataManager->getFieldHandler(_handlerId);
95   MEDCALC::MeshHandler* meshHandler = dataManager->getMeshHandler(fieldHandler->meshid);
96   MEDCALC::DatasourceHandler* dataSHandler = dataManager->getDatasourceHandlerFromID(meshHandler->sourceid);
97
98   extractFileName(std::string(dataSHandler->uri));
99
100   _fieldName = fieldHandler->fieldname;
101   _mcFieldType = (MEDCoupling::TypeOfField) fieldHandler->type;
102   _pvFieldType = getPVFieldTypeString(_mcFieldType);
103   _colorByType = _pvFieldType;  // by default the same; overridden in DeflectionShape, VectorField, PointSprite and Contour
104   _meshName = meshHandler->name;
105 }
106
107 void
108 MEDPresentation::extractFileName(const std::string& name)
109 {
110   _fileName = name;
111   if (_fileName.substr(0, 7) != std::string("file://")) {
112     const char* msg = "MEDPresentation(): Data source is not a file! Can not proceed.";
113     STDLOG(msg);
114     throw MEDPresentationException(msg);
115   }
116   _fileName = _fileName.substr(7, _fileName.size());
117 }
118
119 MEDPresentation::~MEDPresentation()
120 {
121   STDLOG("~MEDPresentation(): clear display");
122   {
123     MEDPyLockWrapper lock;
124     std::ostringstream oss;
125
126     try {
127       oss << "pvs.Hide(" << _objVar <<  ", view=" << getRenderViewVar() << ");";
128       execPyLine(oss.str());
129       // :TRICKY: The two following lines raise an exception when closing MED module
130       //          after sequence: MED - load file - PARAVIS - MED - close SALOME
131       //          (see Mantis #23461)
132       //execPyLine(getRenderViewVar() + ".ResetCamera();");
133       //execPyLine("pvs.Render();");
134     }
135     catch(SALOME::SALOME_Exception&) {
136     }
137   }
138 }
139
140 void
141 MEDPresentation::generatePipeline()
142 {
143   // Might be more complicated in the future:
144
145   this->internalGeneratePipeline();
146 }
147
148 //void
149 //MEDPresentation::pushPyObjects(PyObjectId obj, PyObjectId disp)
150 //{
151 //  _pipeline.push_back(obj);
152 //  _display.push_back(disp);
153 //}
154
155 void
156 MEDPresentation::pushAndExecPyLine(const std::string & lin)
157 {
158   execPyLine(lin);
159   _pythonCmds.push_back(lin);
160 }
161
162 void
163 MEDPresentation::execPyLine(const std::string & lin)
164 {
165   MEDPyLockWrapper lock;
166   STDLOG("@@@@ MEDPresentation::execPyLine() about to exec >> " << lin);
167   if(PyRun_SimpleString(lin.c_str()))
168     {
169       std::ostringstream oss;
170       oss << "MEDPresentation::execPyLine(): following Python command failed!\n";
171       oss << ">> " << lin;
172       STDLOG(oss.str());
173       throw KERNEL::createSalomeException(oss.str().c_str());
174     }
175 }
176
177 void
178 MEDPresentation::setStringProperty(const std::string& propName, const std::string& propValue)
179 {
180   _propertiesStr[propName] = propValue;
181 }
182
183 const std::string
184 MEDPresentation::getStringProperty(const std::string& propName) const
185 {
186   std::map<std::string, std::string>::const_iterator it = _propertiesStr.find(propName);
187   if (it != _propertiesStr.end()) {
188       return (*it).second;
189   }
190   else {
191       STDLOG("MEDPresentation::getStringProperty(): no property named " + propName);
192       throw MEDPresentationException("MEDPresentation::getStringProperty(): no property named " + propName);
193   }
194 }
195
196 void
197 MEDPresentation::setIntProperty(const std::string& propName, const int propValue)
198 {
199   _propertiesInt[propName] = propValue;
200 }
201
202 int
203 MEDPresentation::getIntProperty(const std::string& propName) const
204 {
205   std::map<std::string, int>::const_iterator it = _propertiesInt.find(propName);
206   if (it != _propertiesInt.end()) {
207       return (*it).second;
208   }
209   else {
210       STDLOG("MEDPresentation::getIntProperty(): no property named " + propName);
211       throw MEDPresentationException("MEDPresentation::getIntProperty(): no property named " + propName);
212   }
213 }
214
215  void
216  MEDPresentation::dumpIntProperties() const
217  {
218    std::map<std::string, int>::const_iterator it = _propertiesInt.begin();
219    STDLOG("@@@ Dumping INT properties");
220    for(; it != _propertiesInt.end(); ++it)
221      {
222        std::ostringstream oss;
223        oss << (*it).first << "  ->   " << (*it).second;
224        STDLOG(oss.str());
225      }
226  }
227
228  void
229  MEDPresentation::dumpStringProperties() const
230  {
231    std::map<std::string, std::string>::const_iterator it = _propertiesStr.begin();
232    STDLOG("@@@ Dumping STR properties");
233    for(; it != _propertiesStr.end(); ++it)
234      {
235        std::ostringstream oss;
236        oss << (*it).first << "  ->   " << (*it).second;
237        STDLOG(oss.str());
238      }
239  }
240
241  void
242  MEDPresentation::internalGeneratePipeline()
243  {
244    MEDPyLockWrapper lock;
245    pushAndExecPyLine( "import pvsimple as pvs;");
246    pushAndExecPyLine( "import medcalc");
247  }
248
249
250 /**
251 * @return a borrowed reference. Do not DECRREF!
252 */
253 PyObject*
254 MEDPresentation::getPythonObjectFromMain(const char* python_var) const
255 {
256   if (! _globalDict)
257     {
258       // All the calls below returns *borrowed* references
259       PyObject* main_module = PyImport_AddModule((char*)"__main__");
260       _globalDict = PyModule_GetDict(main_module);
261     }
262   return PyDict_GetItemString(_globalDict, python_var);
263 }
264
265 std::string
266 MEDPresentation::getPVFieldTypeString(MEDCoupling::TypeOfField fieldType) const
267 {
268   switch(fieldType)
269   {
270     case MEDCoupling::ON_CELLS:
271       return "CELLS";
272     case MEDCoupling::ON_NODES:
273       return "POINTS";
274     case MEDCoupling::ON_GAUSS_PT:
275       return "POINTS"; // because internally after application of the ELGA filter, the field will appear as a POINT field
276     case MEDCoupling::ON_GAUSS_NE:
277       return "POINTS"; // because internally after application of the ELNO mesh filter, the field will appear as a POINT field
278     default:
279       STDLOG("MEDPresentation::getPVFieldTypeString() -- Not implemented ! ELNO field?");
280       return "";
281   }
282 }
283
284 std::string
285 MEDPresentation::getRenderViewVar() const
286 {
287   std::ostringstream oss;
288   oss << "__view" << _renderViewPyId;
289   return oss.str();
290 }
291
292 /*!
293  * Creates the MEDReader source in the pipeline, and potentially apply GAUSS/ELNO filters.
294  */
295 void
296 MEDPresentation::createSource()
297 {
298   std::string typ;
299   switch(_mcFieldType) {
300     case MEDCoupling::ON_CELLS: typ = "P0"; break;
301     case MEDCoupling::ON_NODES: typ = "P1"; break;
302     case MEDCoupling::ON_GAUSS_PT: typ = "GAUSS"; break;
303     case MEDCoupling::ON_GAUSS_NE: typ = "GSSNE"; break;
304     default:
305       const char * msg ="MEDPresentation::createSource(): field type not impl. yet!";
306       STDLOG(msg);
307       throw KERNEL::createSalomeException(msg);
308   }
309
310   std::ostringstream oss;
311   oss << _srcObjVar << " = pvs.MEDReader(FileName=r'" << _fileName << "');";
312   pushAndExecPyLine(oss.str()); oss.str("");
313   oss << "medcalc.SelectSourceField(" << _srcObjVar << ", '" << _meshName << "', '"
314       << _fieldName << "', '" << typ << "');";
315   pushAndExecPyLine(oss.str()); oss.str("");
316   // Generate complete vector fields: fields with 2 components will copied into <name>_vector and
317   // have a third null component added.
318   oss << _srcObjVar << ".GenerateVectors = 1;";
319   pushAndExecPyLine(oss.str()); oss.str("");
320
321   // Make sure this is set so we stick to time steps:
322   pushAndExecPyLine("pvs.GetAnimationScene().PlayMode = 'Snap To TimeSteps'");
323
324   // Deal with GAUSS fields:
325   if(_mcFieldType == MEDCoupling::ON_GAUSS_PT)
326     {
327       std::ostringstream oss, oss2;
328       oss2 << "__srcObj" << GeneratePythonId();
329       oss << oss2.str() << " = pvs.ELGAfieldToPointGaussian(Input=" << _srcObjVar << ");";
330       pushAndExecPyLine(oss.str()); oss.str("");
331       // Now the source becomes the result of the CellDatatoPointData:
332       _srcObjVar = oss2.str();
333       oss << _srcObjVar << ".SelectSourceArray = ['CELLS', 'ELGA@0'];";
334       pushAndExecPyLine(oss.str()); oss.str("");
335     }
336   if(_mcFieldType == MEDCoupling::ON_GAUSS_NE)
337     {
338       std::ostringstream oss, oss2;
339       oss2 << "__srcObj" << GeneratePythonId();
340       oss << oss2.str() << " = pvs.ELNOfieldToSurface(Input=" << _srcObjVar << ");";
341       pushAndExecPyLine(oss.str()); oss.str("");
342       // Now the source becomes the result of the CellDatatoPointData:
343       _srcObjVar = oss2.str();
344     }
345 }
346
347 void
348 MEDPresentation::setOrCreateRenderView()
349 {
350   std::ostringstream oss2;
351
352   std::string view(getRenderViewVar());
353   oss2 << "pvs._DisableFirstRenderCameraReset();";
354   pushAndExecPyLine(oss2.str()); oss2.str("");
355   if (_viewMode == MEDCALC::VIEW_MODE_OVERLAP) {
356       // this might potentially re-assign to an existing view variable, but this is OK, we
357       // normally reassign exactly the same RenderView object.
358       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');";
359       pushAndExecPyLine(oss2.str()); oss2.str("");
360   } else if (_viewMode == MEDCALC::VIEW_MODE_REPLACE) {
361       // same as above
362       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');";
363       pushAndExecPyLine(oss2.str()); oss2.str("");
364       oss2 << "pvs.active_objects.source and pvs.Hide(view=" << view << ");";
365       pushAndExecPyLine(oss2.str()); oss2.str("");
366       oss2 << "pvs.Render();";
367       pushAndExecPyLine(oss2.str()); oss2.str("");
368   } else if (_viewMode == MEDCALC::VIEW_MODE_NEW_LAYOUT) {
369       oss2 <<  "__layout1 = pvs.servermanager.misc.ViewLayout(registrationGroup='layouts');";
370       pushAndExecPyLine(oss2.str()); oss2.str("");
371       oss2 << view << " = pvs.CreateView('RenderView');";
372       pushAndExecPyLine(oss2.str()); oss2.str("");
373   } else if (_viewMode == MEDCALC::VIEW_MODE_SPLIT_VIEW) {
374       oss2 << view << " = pvs.CreateView('RenderView');";
375       pushAndExecPyLine(oss2.str()); oss2.str("");
376   }
377 }
378
379 void
380 MEDPresentation::resetCameraAndRender()
381 {
382   pushAndExecPyLine(getRenderViewVar() + ".ResetCamera();");
383   pushAndExecPyLine("pvs.Render();");
384 }
385
386 void
387 MEDPresentation::selectFieldComponent()
388 {
389   std::ostringstream oss, oss_l;
390   std::string ret;
391
392   if (_selectedComponentIndex != -1)
393     {
394       oss << _lutVar << ".VectorMode = 'Component';";
395       pushAndExecPyLine(oss.str()); oss.str("");
396       oss << _lutVar << ".VectorComponent = " << _selectedComponentIndex << ";";
397       pushAndExecPyLine(oss.str()); oss.str("");
398     }
399   else  // Euclidean norm
400     {
401       oss << _lutVar << ".VectorMode = 'Magnitude';";
402       pushAndExecPyLine(oss.str()); oss.str("");
403     }
404 }
405
406 /**
407  * Needs the LUT, so to be called after selectColorMap for the first time.
408  */
409 void
410 MEDPresentation::scalarBarTitle()
411 {
412   // get selected component name:
413   std::string compoName;
414   if (_selectedComponentIndex != -1)
415     {
416       std::ostringstream oss1;
417       oss1 << MEDPresentation::PROP_COMPONENT << _selectedComponentIndex;
418       compoName = getStringProperty(oss1.str());
419     }
420   else
421     {
422       if (getIntProperty(MEDPresentation::PROP_NB_COMPONENTS) == 1)
423         compoName = "";
424       else
425         compoName = "Magnitude";
426     }
427   std::ostringstream oss;
428   oss << "pvs.GetScalarBar(" << _lutVar << ").ComponentTitle = '" << compoName << "';";
429   pushAndExecPyLine(oss.str()); oss.str("");
430 }
431
432 void
433 MEDPresentation::selectColorMap()
434 {
435   std::ostringstream oss, oss2;
436
437   oss2 << _lutVar << " = pvs.GetColorTransferFunction('" << _fieldName << "');";
438   pushAndExecPyLine(oss2.str());
439
440   switch (_colorMap) {
441   case MEDCALC::COLOR_MAP_BLUE_TO_RED_RAINBOW:
442     oss << _lutVar << ".ApplyPreset('Blue to Red Rainbow',True);";
443     break;
444   case MEDCALC::COLOR_MAP_COOL_TO_WARM:
445     oss << _lutVar << ".ApplyPreset('Cool to Warm',True);";
446     break;
447   default:
448     STDLOG("MEDPresentation::getColorMapCommand(): invalid colormap!");
449     throw KERNEL::createSalomeException("MEDPresentation::getColorMapCommand(): invalid colormap!");
450   }
451   pushAndExecPyLine(oss.str());
452
453   selectFieldComponent(); // somehow PV keeps the LUT parameters of the previous presentation, so better reset this.
454 }
455
456 void
457 MEDPresentation::showObject()
458 {
459   std::ostringstream oss;
460   oss << _dispVar << " = pvs.Show(" << _objVar << ", " << getRenderViewVar() << ");";
461   pushAndExecPyLine(oss.str());
462 }
463
464 void
465 MEDPresentation::showScalarBar()
466 {
467   std::ostringstream oss;
468   oss << _dispVar <<  ".SetScalarBarVisibility(" << getRenderViewVar() << ", True);";
469   pushAndExecPyLine(oss.str());
470 }
471
472 void
473 MEDPresentation::colorBy()
474 {
475   std::ostringstream oss;
476   oss << "pvs.ColorBy(" << _dispVar << ", ('" << _colorByType << "', '" << _fieldName << "'));";
477   pushAndExecPyLine(oss.str());
478 }
479
480 void
481 MEDPresentation::rescaleTransferFunction()
482 {
483   std::ostringstream oss;
484   switch(_sbRange)
485   {
486     case MEDCALC::SCALAR_BAR_ALL_TIMESTEPS:
487       oss << _dispVar << ".RescaleTransferFunctionToDataRangeOverTime();";
488       break;
489     case MEDCALC::SCALAR_BAR_CURRENT_TIMESTEP:
490       oss << _dispVar << ".RescaleTransferFunctionToDataRange(False);";
491       break;
492     default:
493       STDLOG("MEDPresentation::getRescaleCommand(): invalid range!");
494       throw KERNEL::createSalomeException("MEDPresentation::getRescaleCommand(): invalid range!");
495   }
496   pushAndExecPyLine(oss.str()); oss.str("");
497   // Get min-max
498   oss << _rangeVar << " = [" << _dispVar << ".LookupTable.RGBPoints[0], " << _dispVar << ".LookupTable.RGBPoints[-4]];";
499   pushAndExecPyLine(oss.str());
500
501   // Adapt scalar bar title
502   scalarBarTitle();
503 }
504
505
506
507 int
508 MEDPresentation::GeneratePythonId()
509 {
510   static int INIT_ID = 0;
511   return INIT_ID++;
512 }
513
514 bool
515 MEDPresentation::activateView()
516 {
517   MEDPyLockWrapper lock;
518
519   execPyLine("__alive = " + getRenderViewVar() + " in pvs.GetRenderViews()");
520   PyObject * obj = getPythonObjectFromMain("__alive");
521   bool alive = true;
522   if (obj && PyBool_Check(obj))
523     alive = (obj == Py_True);
524
525   if (alive)
526     // The view is still there,just activate it:
527     pushAndExecPyLine("pvs.SetActiveView(" + getRenderViewVar() + ");");
528   else
529     {
530       // The view disappeared, recreate it in a new layout. The transfer of the objects is to be done by the caller.
531       std::ostringstream oss;
532       oss <<  "pvs.servermanager.misc.ViewLayout(registrationGroup='layouts');";
533       pushAndExecPyLine(oss.str()); oss.str("");
534       oss << getRenderViewVar() << " = pvs.CreateView('RenderView');";
535       pushAndExecPyLine(oss.str()); oss.str("");
536     }
537   return alive;
538 }
539
540 /**!
541  * Called when the view has been recreated (because the user closed it).
542  * All the objects and set up are re-shown in the new view (which is stored in the same Python variable).
543  */
544 void
545 MEDPresentation::recreateViewSetup()
546 {
547   showObject();
548   colorBy();
549   showScalarBar();
550   selectColorMap();
551   rescaleTransferFunction();
552   resetCameraAndRender();
553 }
554
555 std::string
556 MEDPresentation::paravisDump() const
557 {
558   using namespace std;
559   ostringstream oss;
560   for (vector<string>::const_iterator it=_pythonCmds.begin(); it != _pythonCmds.end(); ++it)
561     {
562       oss << (*it);
563       oss << "\n";
564     }
565   return oss.str();
566 }
567
568 /**
569  * Query all available component names for the field associated with this presentation.
570  * Fills in all the corresponding string properties:
571  *  - PROP_COMPONENT1
572  *  - PROP_COMPONENT2
573  *    etc...
574  *  and the number of components.
575  */
576 void
577 MEDPresentation::fillAvailableFieldComponents()
578 {
579   MEDPyLockWrapper lock;  // GIL!
580   std::string typ;
581
582   if(_pvFieldType == "CELLS") {
583       typ = "CellData";
584   }
585   else if (_pvFieldType == "POINTS") {
586       typ = "PointData";
587   }
588   else {
589       std::string msg("Unsupported spatial discretisation: " + _pvFieldType);
590       STDLOG(msg);
591       throw KERNEL::createSalomeException(msg.c_str());
592   }
593
594   std::ostringstream oss;
595   oss << "__nbCompo = " << _srcObjVar << "." << typ << ".GetArray('" <<  _fieldName << "').GetNumberOfComponents();";
596   execPyLine(oss.str());
597   PyObject* p_obj = getPythonObjectFromMain("__nbCompo");
598   long nbCompo;
599   if (p_obj && PyLong_Check(p_obj))
600     nbCompo = PyLong_AS_LONG(p_obj);
601   else
602     {
603       STDLOG("Unexpected Python error");
604       throw KERNEL::createSalomeException("Unexpected Python error");
605     }
606   setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, nbCompo);
607
608   // if the field is not a vector (2 or 3 components), select the first component of the tensor,
609   // like in WidgetPresentationParameters::setComponents
610   if (!(nbCompo > 1 && nbCompo <= 3))
611     _selectedComponentIndex = 0;
612
613   for (long i = 0; i<nbCompo; i++)
614     {
615       std::ostringstream oss2;
616       oss2 << "__compo = " << _srcObjVar << "." << typ << ".GetArray('" <<  _fieldName << "').GetComponentName(" << i << ");";
617       execPyLine(oss2.str());
618       PyObject* p_obj = getPythonObjectFromMain("__compo");
619       std::string compo;
620       if (p_obj && PyUnicode_Check(p_obj))
621         compo = std::string(Py_EncodeLocale(PyUnicode_AS_UNICODE(p_obj), NULL));  // pointing to internal Python memory, so make a copy!!
622       else
623         {
624           STDLOG("Unexpected Python error");
625           throw KERNEL::createSalomeException("Unexpected Python error");
626         }
627       std::ostringstream oss_p;
628       oss_p << MEDPresentation::PROP_COMPONENT << i;
629       setStringProperty(oss_p.str(), compo);
630     }
631 }
632
633 /**
634  * In case where a CELLS field needs to be converted to POINT field.
635  * This updates the source object to become the result of the CellDatatoPointData filter.
636  */
637 void
638 MEDPresentation::applyCellToPointIfNeeded()
639 {
640   if (_pvFieldType == "CELLS")
641     {
642       std::ostringstream oss, oss2;
643       // Apply Cell data to point data:
644       oss2 << "__srcObj" << GeneratePythonId();
645       oss << oss2.str() << " = pvs.CellDatatoPointData(Input=" << _srcObjVar << ");";
646       pushAndExecPyLine(oss.str()); oss.str("");
647       // Now the source becomes the result of the CellDatatoPointData:
648       _srcObjVar = oss2.str();
649     }
650 }
651
652 ///**
653 // * Convert a vector field into a 3D vector field:
654 // *  - if the vector field is already 3D, nothing to do
655 // *  - if it is 2D, then add a null component
656 // *  - otherwise (tensor field, scalar field) throw
657 // */
658 //void
659 //MEDPresentation::convertTo3DVectorField()
660 //{
661 //  std::ostringstream oss, oss1, oss2, oss3;
662 //
663 //  int nbCompo = getIntProperty(MEDPresentation::PROP_NB_COMPONENTS);
664 //  if (nbCompo < 2 || nbCompo > 3)
665 //    {
666 //      oss << "The field '" << _fieldName << "' must have 2 or 3 components for this presentation!";
667 //      STDLOG(oss.str());
668 //      throw KERNEL::createSalomeException(oss.str().c_str());
669 //    }
670 //  if (nbCompo == 3)
671 //    return;
672 //
673 //  // Apply calculator:
674 //  oss2 << "__srcObj" << GeneratePythonId();
675 //  oss << oss2.str() << " = pvs.Calculator(Input=" << _srcObjVar << ");";
676 //  pushAndExecPyLine(oss.str()); oss.str("");
677 //  // Now the source becomes the result of the CellDatatoPointData:
678 //  _srcObjVar = oss2.str();
679 //  std::string typ;
680 //  if(_pvFieldType == "CELLS")
681 //    typ = "Cell Data";
682 //  else if(_pvFieldType == "POINTS")
683 //    typ = "Point Data";
684 //  else
685 //    {
686 //      oss3 << "Field '" << _fieldName << "' has invalid field type";
687 //      STDLOG(oss3.str());
688 //      throw KERNEL::createSalomeException(oss3.str().c_str());
689 //    }
690 //  oss << _srcObjVar << ".AttributeMode = '" <<  typ << "';";
691 //  pushAndExecPyLine(oss.str()); oss.str("");
692 //  oss << _srcObjVar << ".ResultArrayName = '" <<  _fieldName << "_CALC';";  // will never be needed I think
693 //  pushAndExecPyLine(oss.str()); oss.str("");
694 //  oss << _srcObjVar << ".Function = '" <<  _fieldName << "_0*iHat + " << _fieldName << "_1*jHat + 0.0*zHat';";
695 //  pushAndExecPyLine(oss.str()); oss.str("");
696 //}