Salome HOME
Copyright update 2022
[modules/med.git] / src / MEDCalc / cmp / MEDPresentationContour.cxx
index ee4628505aef623b148b0ff522c007eebc8cff3b..bb063be74e01d8a6bbe71f7d2a292ae8545552ba 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016  CEA/DEN, EDF R&D
+// Copyright (C) 2016-2022  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,7 @@
 
 const std::string MEDPresentationContour::TYPE_NAME = "MEDPresentationContour";
 const std::string MEDPresentationContour::PROP_NB_CONTOUR = "nbContour";
+const std::string MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID = "contourComponent";
 
 MEDPresentationContour::MEDPresentationContour(const MEDCALC::ContourParameters& params,
                                                const MEDCALC::ViewModeType viewMode) :
@@ -34,14 +35,59 @@ MEDPresentationContour::MEDPresentationContour(const MEDCALC::ContourParameters&
         _params(params)
 {
   setIntProperty(MEDPresentationContour::PROP_NB_CONTOUR, params.nbContours);
+  setIntProperty(MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID, 0);
+  std::stringstream oss;
+  oss << "__contourProgrammable" << GeneratePythonId();
+  _countourProgrammableVar = oss.str();
+}
+
+void
+MEDPresentationContour::initProgFilter() {
+  std::ostringstream oss;
+  std::string typ = "PointData"; // Contour Filter is applicable only to Point Data
+  oss << _countourProgrammableVar << " = pvs.ProgrammableFilter(Input = " << _srcObjVar << ");";
+  oss << _countourProgrammableVar << ".Script = \"\"\"import numpy as np" << std::endl;
+  oss << "import paraview.vtk.numpy_interface.dataset_adapter as dsa" << std::endl;
+  oss << "input0 = inputs[0]" << std::endl;
+  oss << "inputDataArray=input0." << typ << "['" << _fieldName << "']" << std::endl;
+  oss << "npa = inputDataArray.GetArrays()" << std::endl;
+  oss << "if type(npa) == list:" << std::endl;
+  oss << "\tarrs = []" << std::endl;
+  oss << "\tfor a in npa:" << std::endl;
+  oss << "\t\tmgm = np.linalg.norm(a, axis = -1)" << std::endl;
+  oss << "\t\tmga = mgm.reshape(mgm.size, 1)" << std::endl;
+  oss << "\t\tarrs.append(mga)" << std::endl;
+  oss << "\tca = dsa.VTKCompositeDataArray(arrs)" << std::endl;
+  oss << "\toutput." << typ << ".append(ca, '" << _fieldName << "_magnitude')" << std::endl;
+  oss << "else:" << std::endl;
+  oss << "\tmgm = np.linalg.norm(npa, axis = -1)" << std::endl;
+  oss << "\tmga = mgm.reshape(mgm.size, 1)" << std::endl;
+  oss << "\toutput." << typ << ".append(mga, '" << _fieldName << "_magnitude')" << std::endl;
+  for (std::vector<std::string>::size_type ii = 1; ii < _nbComponents + 1 ; ii++) {
+    oss << "dataArray" << ii << " = inputDataArray[:, [" << ii - 1 << "]]" << std::endl;
+    oss << "output." << typ << ".append(dataArray" << ii << ", '" << _fieldName << "_" << ii <<  "')" << std::endl;
+  }
+  oss << "\"\"\"" << std::endl;
+  pushAndExecPyLine(oss.str());
+}
+
+void
+MEDPresentationContour::initFieldMeshInfos()
+{
+  MEDPresentation::initFieldMeshInfos();
+  _colorByType = "POINTS";
 }
 
 void
 MEDPresentationContour::setNumberContours()
 {
   std::ostringstream oss;
+  std::string aVar = _srcObjVar;
+  if (_nbComponents > 1) {
+    aVar = _countourProgrammableVar;
+  }
 
-  oss << "min_max = " << _srcObjVar << ".PointData.GetArray('" << _fieldName << "').GetRange();";
+  oss << "min_max = " << aVar << ".PointData.GetArray('" << getContourComponentName() << "').GetRange();";
   pushAndExecPyLine(oss.str()); oss.str("");
   oss << "delta = (min_max[1]-min_max[0])/float(" << _params.nbContours << ");";
   pushAndExecPyLine(oss.str()); oss.str("");
@@ -57,40 +103,53 @@ MEDPresentationContour::internalGeneratePipeline()
   MEDPyLockWrapper lock;
 
   createSource();
+  setTimestamp();
 
   // Populate internal array of available components:
   fillAvailableFieldComponents();
-  if (getIntProperty(MEDPresentation::PROP_NB_COMPONENTS) > 1)
-    {
-      const char * msg = "Contour presentation only works for scalar field!"; // this message will appear in GUI too
-      STDLOG(msg);
-      throw KERNEL::createSalomeException(msg);
-    }
   if (_params.nbContours < 1)
-    {
-      const char * mes = "Invalid number of contours!";
-      STDLOG(mes);
-      throw KERNEL::createSalomeException(mes);
-    }
-
-  setOrCreateRenderView(); // instanciate __viewXXX
+  {
+    const char * mes = "Invalid number of contours!";
+    STDLOG(mes);
+    throw KERNEL::createSalomeException(mes);
+  }
+  setOrCreateRenderView(); // instantiate __viewXXX, needs to be after the exception above otherwise previous elements in the view will be hidden.
 
   // Contour needs point data:
   applyCellToPointIfNeeded();
-
   std::ostringstream oss;
-  oss << _objVar << " = pvs.Contour(Input=" << _srcObjVar << ");";
-  pushAndExecPyLine(oss.str()); oss.str("");
 
-  showObject();
+  // Calculate component
+  if (_nbComponents > 1)
+  {
+    pushAndExecPyLine(oss.str()); oss.str("");
+    initProgFilter();
+    _nbComponentsInThresholdInput = 1; // Because we extract all components as a separate array usign Programmable Filter
+    _selectedComponentIndex = 0;
+    oss << _objVar << " = pvs.Contour(Input=" << _countourProgrammableVar << ");";
+    pushAndExecPyLine(oss.str()); oss.str("");
+
+    oss << _objVar << ".ContourBy = ['POINTS', '" << _fieldName << "_magnitude" << "'];";
+    pushAndExecPyLine(oss.str());
+  }
+  else
+  {
+    oss << _objVar << " = pvs.Contour(Input=" << _srcObjVar << ");";
+    pushAndExecPyLine(oss.str()); oss.str("");
+
+    oss << _objVar << ".ContourBy = ['POINTS', '" << _fieldName << "'];";
+    pushAndExecPyLine(oss.str()); oss.str("");
+  }
 
-  oss << _objVar << ".ContourBy = ['POINTS', '" << _fieldName << "'];";
+  // Colorize contour
+  oss << _objVar << ".ComputeScalars = 1;";
   pushAndExecPyLine(oss.str()); oss.str("");
 
   // Set number of contours
   setNumberContours();
 
-  colorBy("POINTS");    // necessarily POINTS because of the conversion above
+  showObject();
+  colorBy();
   showScalarBar();
   selectColorMap();
   rescaleTransferFunction();
@@ -103,8 +162,14 @@ MEDPresentationContour::updatePipeline(const MEDCALC::ContourParameters& params)
   if (params.fieldHandlerId != _params.fieldHandlerId)
     throw KERNEL::createSalomeException("Unexpected updatePipeline error! Mismatching fieldHandlerId!");
 
-  if (params.scalarBarRange != _params.scalarBarRange)
-    updateScalarBarRange<MEDPresentationContour, MEDCALC::ContourParameters>(params.scalarBarRange);
+  if (params.scalarBarRange != _params.scalarBarRange ||
+      params.hideDataOutsideCustomRange != _params.hideDataOutsideCustomRange ||
+    params.scalarBarRangeArray[0] != _params.scalarBarRangeArray[0] ||
+    params.scalarBarRangeArray[1] != _params.scalarBarRangeArray[1])
+    updateScalarBarRange<MEDPresentationContour, MEDCALC::ContourParameters>(params.scalarBarRange,
+                                                                             params.hideDataOutsideCustomRange,
+                                                                             params.scalarBarRangeArray[0],
+                                                                             params.scalarBarRangeArray[1]);
   if (params.colorMap != _params.colorMap)
     updateColorMap<MEDPresentationContour, MEDCALC::ContourParameters>(params.colorMap);
 
@@ -118,6 +183,16 @@ MEDPresentationContour::updatePipeline(const MEDCALC::ContourParameters& params)
         }
       updateNbContours(params.nbContours);
     }
+
+  if (std::string(params.contourComponent) != std::string(_params.contourComponent))
+    updateContourComponent(std::string(params.contourComponent));
+
+  if (params.visibility != _params.visibility)
+    updateVisibility<MEDPresentationContour, MEDCALC::ContourParameters>(params.visibility);
+
+  if (params.scalarBarVisibility != _params.scalarBarVisibility)
+    updateScalarBarVisibility<MEDPresentationContour, MEDCALC::ContourParameters>(params.scalarBarVisibility);
+
 }
 
 void
@@ -135,3 +210,93 @@ MEDPresentationContour::updateNbContours(const int nbContours)
     pushAndExecPyLine("pvs.Render();");
   }
 }
+
+void
+MEDPresentationContour::updateContourComponent(const std::string& newCompo)
+{
+  _params.contourComponent = newCompo.c_str();
+
+  int id = getContourComponentId();
+
+  // GUI helper:
+  setIntProperty(MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID, id);
+
+  // Update the pipeline:
+  {
+    MEDPyLockWrapper lock;
+    std::ostringstream oss;
+    oss << _objVar << ".ContourBy = ['POINTS', '" << getContourComponentName() << "'];";
+    pushAndExecPyLine(oss.str()); oss.str("");
+    scalarBarTitle();
+    pushAndExecPyLine("pvs.Render();");
+  }
+}
+
+
+int MEDPresentationContour::getContourComponentId() const {
+  int result = -1;
+  if (std::string(_params.contourComponent) == "") { // Magnitude
+    result = 0;
+  }
+  for (std::vector<std::string>::size_type i = 0; i < _nbComponents; i++) {
+    std::ostringstream oss_p;
+    oss_p << MEDPresentation::PROP_COMPONENT << i;
+    std::string compo = getStringProperty(oss_p.str());
+    if (std::string(_params.contourComponent) == compo) {
+      result = i + 1;
+      break;
+    }
+  }
+  if (result == -1) {
+    std::ostringstream oss;
+    oss << "MEDPresentationContour::getContourComponentId(): unknown component '" <<_params.contourComponent 
+      <<  "' !\n";
+    STDLOG(oss.str());
+    throw KERNEL::createSalomeException(oss.str().c_str());
+  }
+  return result;
+}
+
+std::string MEDPresentationContour::getContourComponentName() const {
+  std::ostringstream result;
+  result << _fieldName;
+  if (_nbComponents > 1) {
+    int id = getContourComponentId();
+    switch (id) {
+    case 0: result << "_magnitude"; break;
+    default: result << "_" << id; break;
+    }
+  }
+  return result.str();
+}
+
+std::string MEDPresentationContour::getFieldName() const {
+  return getContourComponentName();
+}
+
+void
+MEDPresentationContour::scalarBarTitle()
+{
+  if (_nbComponents >  1) {
+    // get selected component name:
+    int id = getContourComponentId();
+    std::string compoName;
+    if (id != 0)
+    {
+      std::ostringstream oss1;
+      oss1 << MEDPresentation::PROP_COMPONENT << id - 1;
+      compoName = getStringProperty(oss1.str());
+    }
+    else
+    {
+        compoName = "Magnitude";
+    }
+    std::ostringstream oss;
+      oss << "pvs.GetScalarBar(" << getLutVar() << ").Title = '" << _fieldName << "';";
+    oss << "pvs.GetScalarBar(" << getLutVar() << ").ComponentTitle = '" << compoName << "';";
+    pushAndExecPyLine(oss.str()); oss.str("");
+  }
+  else {
+    MEDPresentation::scalarBarTitle();
+  }
+}
\ No newline at end of file