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