Salome HOME
775a1a157ea57bb7685b5c3eda216e918b371898
[modules/med.git] / src / MEDCalc / cmp / MEDPresentationContour.cxx
1 // Copyright (C) 2016-2023  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 #include "MEDPresentationContour.hxx"
21
22 #include <SALOME_KernelServices.hxx>
23 #undef LOG  // should be fixed in KERNEL - double definition
24 #include <Basics_Utils.hxx>
25
26 #include <sstream>
27
28 const std::string MEDPresentationContour::TYPE_NAME = "MEDPresentationContour";
29 const std::string MEDPresentationContour::PROP_NB_CONTOUR = "nbContour";
30 const std::string MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID = "contourComponent";
31
32 MEDPresentationContour::MEDPresentationContour(const MEDCALC::ContourParameters& params,
33                                                const MEDCALC::ViewModeType viewMode) :
34         MEDPresentation(params.fieldHandlerId, TYPE_NAME, viewMode, params.colorMap, params.scalarBarRange),
35         _params(params)
36 {
37   setIntProperty(MEDPresentationContour::PROP_NB_CONTOUR, params.nbContours);
38   setIntProperty(MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID, 0);
39   std::stringstream oss;
40   oss << "__contourProgrammable" << GeneratePythonId();
41   _countourProgrammableVar = oss.str();
42 }
43
44 void
45 MEDPresentationContour::initProgFilter() {
46   std::ostringstream oss;
47   std::string typ = "PointData"; // Contour Filter is applicable only to Point Data
48   oss << _countourProgrammableVar << " = pvs.ProgrammableFilter(Input = " << _srcObjVar << ");";
49   oss << _countourProgrammableVar << ".Script = \"\"\"import numpy as np" << std::endl;
50   oss << "import paraview.vtk.numpy_interface.dataset_adapter as dsa" << std::endl;
51   oss << "input0 = inputs[0]" << std::endl;
52   oss << "inputDataArray=input0." << typ << "['" << _fieldName << "']" << std::endl;
53   oss << "npa = inputDataArray.GetArrays()" << std::endl;
54   oss << "if type(npa) == list:" << std::endl;
55   oss << "\tarrs = []" << std::endl;
56   oss << "\tfor a in npa:" << std::endl;
57   oss << "\t\tmgm = np.linalg.norm(a, axis = -1)" << std::endl;
58   oss << "\t\tmga = mgm.reshape(mgm.size, 1)" << std::endl;
59   oss << "\t\tarrs.append(mga)" << std::endl;
60   oss << "\tca = dsa.VTKCompositeDataArray(arrs)" << std::endl;
61   oss << "\toutput." << typ << ".append(ca, '" << _fieldName << "_magnitude')" << std::endl;
62   oss << "else:" << std::endl;
63   oss << "\tmgm = np.linalg.norm(npa, axis = -1)" << std::endl;
64   oss << "\tmga = mgm.reshape(mgm.size, 1)" << std::endl;
65   oss << "\toutput." << typ << ".append(mga, '" << _fieldName << "_magnitude')" << std::endl;
66   for (std::vector<std::string>::size_type ii = 1; ii < _nbComponents + 1 ; ii++) {
67     oss << "dataArray" << ii << " = inputDataArray[:, [" << ii - 1 << "]]" << std::endl;
68     oss << "output." << typ << ".append(dataArray" << ii << ", '" << _fieldName << "_" << ii <<  "')" << std::endl;
69   }
70   oss << "\"\"\"" << std::endl;
71   pushAndExecPyLine(oss.str());
72 }
73
74 void
75 MEDPresentationContour::initFieldMeshInfos()
76 {
77   MEDPresentation::initFieldMeshInfos();
78   _colorByType = "POINTS";
79 }
80
81 void
82 MEDPresentationContour::setNumberContours()
83 {
84   std::ostringstream oss;
85   std::string aVar = _srcObjVar;
86   if (_nbComponents > 1) {
87     aVar = _countourProgrammableVar;
88   }
89
90   oss << "min_max = " << aVar << ".PointData.GetArray('" << getContourComponentName() << "').GetRange();";
91   pushAndExecPyLine(oss.str()); oss.str("");
92   oss << "delta = (min_max[1]-min_max[0])/float(" << _params.nbContours << ");";
93   pushAndExecPyLine(oss.str()); oss.str("");
94   oss << _objVar << ".Isosurfaces = [min_max[0]+0.5*delta+i*delta for i in range(" << _params.nbContours << ")];";
95   pushAndExecPyLine(oss.str()); oss.str("");
96 }
97
98 void
99 MEDPresentationContour::internalGeneratePipeline()
100 {
101   MEDPresentation::internalGeneratePipeline();
102
103   MEDPyLockWrapper lock;
104
105   createSource();
106   setTimestamp();
107
108   // Populate internal array of available components:
109   fillAvailableFieldComponents();
110   if (_params.nbContours < 1)
111   {
112     const char * mes = "Invalid number of contours!";
113     STDLOG(mes);
114     throw KERNEL::createSalomeException(mes);
115   }
116   setOrCreateRenderView(); // instantiate __viewXXX, needs to be after the exception above otherwise previous elements in the view will be hidden.
117
118   // Contour needs point data:
119   applyCellToPointIfNeeded();
120   std::ostringstream oss;
121
122   // Calculate component
123   if (_nbComponents > 1)
124   {
125     pushAndExecPyLine(oss.str()); oss.str("");
126     initProgFilter();
127     _nbComponentsInThresholdInput = 1; // Because we extract all components as a separate array usign Programmable Filter
128     _selectedComponentIndex = 0;
129     oss << _objVar << " = pvs.Contour(Input=" << _countourProgrammableVar << ");";
130     pushAndExecPyLine(oss.str()); oss.str("");
131
132     oss << _objVar << ".ContourBy = ['POINTS', '" << _fieldName << "_magnitude" << "'];";
133     pushAndExecPyLine(oss.str());
134   }
135   else
136   {
137     oss << _objVar << " = pvs.Contour(Input=" << _srcObjVar << ");";
138     pushAndExecPyLine(oss.str()); oss.str("");
139
140     oss << _objVar << ".ContourBy = ['POINTS', '" << _fieldName << "'];";
141     pushAndExecPyLine(oss.str()); oss.str("");
142   }
143
144   // Colorize contour
145   oss << _objVar << ".ComputeScalars = 1;";
146   pushAndExecPyLine(oss.str()); oss.str("");
147
148   // Set number of contours
149   setNumberContours();
150
151   showObject();
152   colorBy();
153   showScalarBar();
154   selectColorMap();
155   rescaleTransferFunction();
156   resetCameraAndRender();
157 }
158
159 void
160 MEDPresentationContour::updatePipeline(const MEDCALC::ContourParameters& params)
161 {
162   if (params.fieldHandlerId != _params.fieldHandlerId)
163     throw KERNEL::createSalomeException("Unexpected updatePipeline error! Mismatching fieldHandlerId!");
164
165   if (params.scalarBarRange != _params.scalarBarRange ||
166       params.hideDataOutsideCustomRange != _params.hideDataOutsideCustomRange ||
167     params.scalarBarRangeArray[0] != _params.scalarBarRangeArray[0] ||
168     params.scalarBarRangeArray[1] != _params.scalarBarRangeArray[1])
169     updateScalarBarRange<MEDPresentationContour, MEDCALC::ContourParameters>(params.scalarBarRange,
170                                                                              params.hideDataOutsideCustomRange,
171                                                                              params.scalarBarRangeArray[0],
172                                                                              params.scalarBarRangeArray[1]);
173   if (params.colorMap != _params.colorMap)
174     updateColorMap<MEDPresentationContour, MEDCALC::ContourParameters>(params.colorMap);
175
176   if (params.nbContours != _params.nbContours)
177     {
178       if (params.nbContours < 1)
179         {
180           const char * mes = "Invalid number of contours!";
181           STDLOG(mes);
182           throw KERNEL::createSalomeException(mes);
183         }
184       updateNbContours(params.nbContours);
185     }
186
187   if (std::string(params.contourComponent) != std::string(_params.contourComponent))
188     updateContourComponent(std::string(params.contourComponent));
189
190   if (params.visibility != _params.visibility)
191     updateVisibility<MEDPresentationContour, MEDCALC::ContourParameters>(params.visibility);
192
193   if (params.scalarBarVisibility != _params.scalarBarVisibility)
194     updateScalarBarVisibility<MEDPresentationContour, MEDCALC::ContourParameters>(params.scalarBarVisibility);
195
196 }
197
198 void
199 MEDPresentationContour::updateNbContours(const int nbContours)
200 {
201   _params.nbContours = nbContours;
202
203   // GUI helper:
204   setIntProperty(MEDPresentationContour::PROP_NB_CONTOUR, nbContours);
205
206   // Update the pipeline:
207   {
208     MEDPyLockWrapper lock;
209     setNumberContours();
210     pushAndExecPyLine("pvs.Render();");
211   }
212 }
213
214 void
215 MEDPresentationContour::updateContourComponent(const std::string& newCompo)
216 {
217   _params.contourComponent = newCompo.c_str();
218
219   int id = getContourComponentId();
220
221   // GUI helper:
222   setIntProperty(MEDPresentationContour::PROB_CONTOUR_COMPONENT_ID, id);
223
224   // Update the pipeline:
225   {
226     MEDPyLockWrapper lock;
227     std::ostringstream oss;
228     oss << _objVar << ".ContourBy = ['POINTS', '" << getContourComponentName() << "'];";
229     pushAndExecPyLine(oss.str()); oss.str("");
230     scalarBarTitle();
231     pushAndExecPyLine("pvs.Render();");
232   }
233 }
234
235
236 int MEDPresentationContour::getContourComponentId() const {
237   int result = -1;
238   if (std::string(_params.contourComponent) == "") { // Magnitude
239     result = 0;
240   }
241   for (std::vector<std::string>::size_type i = 0; i < _nbComponents; i++) {
242     std::ostringstream oss_p;
243     oss_p << MEDPresentation::PROP_COMPONENT << i;
244     std::string compo = getStringProperty(oss_p.str());
245     if (std::string(_params.contourComponent) == compo) {
246       result = i + 1;
247       break;
248     }
249   }
250   if (result == -1) {
251     std::ostringstream oss;
252     oss << "MEDPresentationContour::getContourComponentId(): unknown component '" <<_params.contourComponent 
253       <<  "' !\n";
254     STDLOG(oss.str());
255     throw KERNEL::createSalomeException(oss.str().c_str());
256   }
257   return result;
258 }
259
260 std::string MEDPresentationContour::getContourComponentName() const {
261   std::ostringstream result;
262   result << _fieldName;
263   if (_nbComponents > 1) {
264     int id = getContourComponentId();
265     switch (id) {
266     case 0: result << "_magnitude"; break;
267     default: result << "_" << id; break;
268     }
269   }
270   return result.str();
271 }
272
273 std::string MEDPresentationContour::getFieldName() const {
274   return getContourComponentName();
275 }
276
277 void
278 MEDPresentationContour::scalarBarTitle()
279 {
280   if (_nbComponents >  1) {
281     // get selected component name:
282     int id = getContourComponentId();
283     std::string compoName;
284     if (id != 0)
285     {
286       std::ostringstream oss1;
287       oss1 << MEDPresentation::PROP_COMPONENT << id - 1;
288       compoName = getStringProperty(oss1.str());
289     }
290     else
291     {
292         compoName = "Magnitude";
293     }
294     std::ostringstream oss;
295       oss << "pvs.GetScalarBar(" << getLutVar() << ").Title = '" << _fieldName << "';";
296     oss << "pvs.GetScalarBar(" << getLutVar() << ").ComponentTitle = '" << compoName << "';";
297     pushAndExecPyLine(oss.str()); oss.str("");
298   }
299   else {
300     MEDPresentation::scalarBarTitle();
301   }
302 }