Salome HOME
e76ad76935ddf784b4250e34fe39073d49a4e4b1
[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 "MEDPyLockWrapper.hxx"
22 #include "MEDFactoryClient.hxx"
23 #include "MEDPresentation.hxx"
24 #include "MEDPresentationException.hxx"
25 #include "MEDCouplingRefCountObject.hxx"
26 #include <SALOME_KernelServices.hxx>
27 #undef LOG
28 #include <Basics_Utils.hxx>
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::ViewModeType viewMode,
41                                  const MEDCALC::ColorMapType colorMap,
42                                  const MEDCALC::ScalarBarRangeType 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       _globalDict(0)
51 {
52   MEDCALC::MEDDataManager_ptr dataManager(MEDFactoryClient::getDataManager());
53   MEDCALC::FieldHandler* fieldHandler = dataManager->getFieldHandler(fieldHandlerId);
54   MEDCALC::MeshHandler* meshHandler = dataManager->getMesh(fieldHandler->meshid);
55   MEDCALC::DatasourceHandler* dataSHandler = dataManager->getDatasourceHandlerFromID(meshHandler->sourceid);
56
57   _fileName = dataSHandler->uri;
58   _fieldName = fieldHandler->fieldname;
59   _mcFieldType = (MEDCoupling::TypeOfField) fieldHandler->type;
60   _pvFieldType = getPVFieldTypeString(_mcFieldType);
61   _meshName = meshHandler->name;
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>(colorMap));
76   setIntProperty(MEDPresentation::PROP_SCALAR_BAR_RANGE, static_cast<int>(sbRange));
77
78   // Python variables:
79   int id = GeneratePythonId();
80   std::ostringstream oss_o, oss_d, oss_l, oss_s, oss_r;
81   oss_o << "__obj" << id;
82   oss_s << "__srcObj" << id;
83   oss_d << "__disp" << id;
84   oss_l << "__lut" << id;
85   oss_r << "__range" << id;
86   _objVar = oss_o.str();
87   _srcObjVar = oss_s.str();
88   _dispVar = oss_d.str();
89   _lutVar = oss_l.str();
90   _rangeVar = oss_r.str();
91 }
92
93 MEDPresentation::~MEDPresentation()
94 {
95   STDLOG("~MEDPresentation(): clear display");
96   {
97     MEDPyLockWrapper lock;
98     std::ostringstream oss_v, oss;
99     oss_v << "__view" << _renderViewPyId;
100     oss << "pvs.Hide(" << _objVar <<  ", view=" << oss_v.str() << ");";
101     oss << "pvs.Render();";
102
103     PyRun_SimpleString(oss.str().c_str());
104   }
105 }
106
107 void
108 MEDPresentation::generatePipeline()
109 {
110   // Might be more complicated in the future:
111
112   this->internalGeneratePipeline();
113 }
114
115 //void
116 //MEDPresentation::pushPyObjects(PyObjectId obj, PyObjectId disp)
117 //{
118 //  _pipeline.push_back(obj);
119 //  _display.push_back(disp);
120 //}
121
122 void
123 MEDPresentation::pushAndExecPyLine(const std::string & lin)
124 {
125   execPyLine(lin);
126   _pythonCmds.push_back(lin);
127 }
128
129 void
130 MEDPresentation::execPyLine(const std::string & lin)
131 {
132   MEDPyLockWrapper lock;
133   STDLOG("@@@@ MEDPresentation::execPyLine() about to exec >> " << lin);
134   if(PyRun_SimpleString(lin.c_str()))
135     {
136       std::ostringstream oss;
137       oss << "MEDPresentation::execPyLine(): following Python command failed!\n";
138       oss << ">> " << lin;
139       STDLOG(oss.str());
140       throw KERNEL::createSalomeException(oss.str().c_str());
141     }
142 }
143
144 void
145 MEDPresentation::setStringProperty(const std::string& propName, const std::string& propValue)
146 {
147   _propertiesStr[propName] = propValue;
148 }
149
150 const std::string
151 MEDPresentation::getStringProperty(const std::string& propName) const
152 {
153   std::map<std::string, std::string>::const_iterator it = _propertiesStr.find(propName);
154   if (it != _propertiesStr.end()) {
155       return (*it).second;
156   }
157   else {
158       STDLOG("MEDPresentation::getStringProperty(): no property named " + propName);
159       throw MEDPresentationException("MEDPresentation::getStringProperty(): no property named " + propName);
160   }
161 }
162
163 void
164 MEDPresentation::setIntProperty(const std::string& propName, const int propValue)
165 {
166   _propertiesInt[propName] = propValue;
167 }
168
169 int
170 MEDPresentation::getIntProperty(const std::string& propName) const
171 {
172   std::map<std::string, int>::const_iterator it = _propertiesInt.find(propName);
173   if (it != _propertiesInt.end()) {
174       return (*it).second;
175   }
176   else {
177       STDLOG("MEDPresentation::getIntProperty(): no property named " + propName);
178       throw MEDPresentationException("MEDPresentation::getIntProperty(): no property named " + propName);
179   }
180 }
181
182  void
183  MEDPresentation::dumpIntProperties() const
184  {
185    std::map<std::string, int>::const_iterator it = _propertiesInt.begin();
186    STDLOG("@@@ Dumping INT properties");
187    for(; it != _propertiesInt.end(); ++it)
188      {
189        std::ostringstream oss;
190        oss << (*it).first << "  ->   " << (*it).second;
191        STDLOG(oss.str());
192      }
193  }
194
195  void
196  MEDPresentation::dumpStringProperties() const
197  {
198    std::map<std::string, std::string>::const_iterator it = _propertiesStr.begin();
199    STDLOG("@@@ Dumping STR properties");
200    for(; it != _propertiesStr.end(); ++it)
201      {
202        std::ostringstream oss;
203        oss << (*it).first << "  ->   " << (*it).second;
204        STDLOG(oss.str());
205      }
206  }
207
208  void
209  MEDPresentation::internalGeneratePipeline()
210  {
211    MEDPyLockWrapper lock;
212    pushAndExecPyLine( "import pvsimple as pvs;");
213    pushAndExecPyLine( "import medcalc");
214  }
215
216
217 /**
218 * @return a borrowed reference. Do not DECRREF!
219 */
220 PyObject*
221 MEDPresentation::getPythonObjectFromMain(const char* python_var) const
222 {
223   if (! _globalDict)
224     {
225       // All the calls below returns *borrowed* references
226       PyObject* main_module = PyImport_AddModule((char*)"__main__");
227       _globalDict = PyModule_GetDict(main_module);
228     }
229   return PyDict_GetItemString(_globalDict, python_var);
230 }
231
232 std::string
233 MEDPresentation::getPVFieldTypeString(MEDCoupling::TypeOfField fieldType) const
234 {
235   switch(fieldType)
236   {
237     case MEDCoupling::ON_CELLS:
238       return "CELLS";
239     case MEDCoupling::ON_NODES:
240       return "POINTS";
241     case MEDCoupling::ON_GAUSS_PT:
242       return "POINTS"; // because internally after application of the ELGA filter, the field will appear as a POINT field
243     default:
244       STDLOG("MEDPresentation::getPVFieldTypeString() -- Not implemented ! ELNO field?");
245       return "";
246   }
247 }
248
249 std::string
250 MEDPresentation::getRenderViewVar() const
251 {
252   std::ostringstream oss;
253   oss << "__view" << _renderViewPyId;
254   return oss.str();
255 }
256
257 /*!
258  * Creates the MEDReader source in the pipeline, and potentially apply GAUSS/ELNO filters.
259  */
260 void
261 MEDPresentation::createSource()
262 {
263   std::string typ;
264   switch(_mcFieldType) {
265     case MEDCoupling::ON_CELLS: typ = "P0"; break;
266     case MEDCoupling::ON_NODES: typ = "P1"; break;
267     case MEDCoupling::ON_GAUSS_PT: typ = "GAUSS"; break;
268     default:
269       const char * msg ="MEDPresentation::createSource(): field type not impl. yet!";
270       STDLOG(msg);
271       throw KERNEL::createSalomeException(msg);
272   }
273
274   std::ostringstream oss;
275   oss << _srcObjVar << " = pvs.MEDReader(FileName='" << _fileName << "');";
276   pushAndExecPyLine(oss.str()); oss.str("");
277   oss << "medcalc.SelectSourceField(" << _srcObjVar << ", '" << _meshName << "', '"
278       << _fieldName << "', '" << typ << "');";
279   pushAndExecPyLine(oss.str()); oss.str("");
280   oss << _srcObjVar << ".GenerateVectors = 1;";
281   pushAndExecPyLine(oss.str()); oss.str("");
282
283   // Deal with GAUSS fields:
284   if(_mcFieldType == MEDCoupling::ON_GAUSS_PT)
285     {
286       std::ostringstream oss, oss2;
287       oss2 << "__srcObj" << GeneratePythonId();
288       oss << oss2.str() << " = pvs.GaussPoints(Input=" << _srcObjVar << ");";
289       pushAndExecPyLine(oss.str()); oss.str("");
290       // Now the source becomes the result of the CellDatatoPointData:
291       _srcObjVar = oss2.str();
292       oss << _srcObjVar << ".SelectSourceArray = ['CELLS', 'ELGA@0'];";
293       pushAndExecPyLine(oss.str()); oss.str("");
294     }
295   if(_mcFieldType == MEDCoupling::ON_GAUSS_NE)
296     {
297       const char * msg ="MEDPresentation::createSource(): ELNO field never tested!";
298       STDLOG(msg);
299       throw KERNEL::createSalomeException(msg);
300
301       std::ostringstream oss, oss2;
302       oss2 << "__srcObj" << GeneratePythonId();
303       oss << oss2.str() << " = pvs.ELNOMesh(Input=" << _srcObjVar << ");";
304       pushAndExecPyLine(oss.str()); oss.str("");
305       // Now the source becomes the result of the CellDatatoPointData:
306       _srcObjVar = oss2.str();
307 //      oss << _srcObjVar << ".SelectSourceArray = ['CELLS', 'ELNO@0'];";
308 //      pushAndExecPyLine(oss.str()); oss.str("");
309     }
310 }
311
312 void
313 MEDPresentation::setOrCreateRenderView()
314 {
315   std::ostringstream oss2;
316
317   std::string view(getRenderViewVar());
318   oss2 << "pvs._DisableFirstRenderCameraReset();";
319   pushAndExecPyLine(oss2.str()); oss2.str("");
320   if (_viewMode == MEDCALC::VIEW_MODE_OVERLAP) {
321       // this might potentially re-assign to an existing view variable, but this is OK, we
322       // normally reassign exaclty the same RenderView object.
323       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');";
324       pushAndExecPyLine(oss2.str()); oss2.str("");
325   } else if (_viewMode == MEDCALC::VIEW_MODE_REPLACE) {
326       // same as above
327       oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');";
328       pushAndExecPyLine(oss2.str()); oss2.str("");
329       oss2 << "pvs.active_objects.source and pvs.Hide(view=" << view << ");";
330       pushAndExecPyLine(oss2.str()); oss2.str("");
331       oss2 << "pvs.Render();";
332       pushAndExecPyLine(oss2.str()); oss2.str("");
333   } else if (_viewMode == MEDCALC::VIEW_MODE_NEW_LAYOUT) {
334       oss2 <<  "__layout1 = pvs.servermanager.misc.ViewLayout(registrationGroup='layouts');";
335       pushAndExecPyLine(oss2.str()); oss2.str("");
336       oss2 << view << " = pvs.CreateView('RenderView');";
337       pushAndExecPyLine(oss2.str()); oss2.str("");
338   } else if (_viewMode == MEDCALC::VIEW_MODE_SPLIT_VIEW) {
339       oss2 << view << " = pvs.CreateView('RenderView');";
340       pushAndExecPyLine(oss2.str()); oss2.str("");
341   }
342 }
343
344 void
345 MEDPresentation::resetCameraAndRender()
346 {
347   pushAndExecPyLine(getRenderViewVar() + ".ResetCamera();");
348   pushAndExecPyLine("pvs.Render();");
349 }
350
351 void
352 MEDPresentation::selectFieldComponent()
353 {
354   std::ostringstream oss, oss_l;
355   std::string ret;
356
357   if (_selectedComponentIndex != -1)
358     {
359       oss << _lutVar << ".VectorMode = 'Component';";
360       pushAndExecPyLine(oss.str()); oss.str("");
361       oss << _lutVar << ".VectorComponent = " << _selectedComponentIndex << ";";
362       pushAndExecPyLine(oss.str()); oss.str("");
363     }
364   else  // Euclidean norm
365     {
366       oss << _lutVar << ".VectorMode = 'Magnitude';";
367       pushAndExecPyLine(oss.str()); oss.str("");
368     }
369 }
370
371 /**
372  * Needs the LUT, so to be called after selectColorMap for the first time.
373  */
374 void
375 MEDPresentation::scalarBarTitle()
376 {
377   // get selected component name:
378   std::string compoName;
379   if (_selectedComponentIndex != -1)
380     {
381       std::ostringstream oss1;
382       oss1 << MEDPresentation::PROP_COMPONENT << _selectedComponentIndex;
383       compoName = getStringProperty(oss1.str());
384     }
385   else
386     {
387       if (getIntProperty(MEDPresentation::PROP_NB_COMPONENTS) == 1)
388         compoName = "";
389       else
390         compoName = "Magnitude";
391     }
392   std::ostringstream oss;
393   oss << "pvs.GetScalarBar(" << _lutVar << ").ComponentTitle = '" << compoName << "';";
394   pushAndExecPyLine(oss.str()); oss.str("");
395 }
396
397 void
398 MEDPresentation::selectColorMap()
399 {
400   std::ostringstream oss, oss2;
401
402   oss2 << _lutVar << " = pvs.GetColorTransferFunction('" << _fieldName << "');";
403   pushAndExecPyLine(oss2.str());
404
405   switch (_colorMap) {
406   case MEDCALC::COLOR_MAP_BLUE_TO_RED_RAINBOW:
407     oss << _lutVar << ".ApplyPreset('Blue to Red Rainbow',True);";
408     break;
409   case MEDCALC::COLOR_MAP_COOL_TO_WARM:
410     oss << _lutVar << ".ApplyPreset('Cool to Warm',True);";
411     break;
412   default:
413     STDLOG("MEDPresentation::getColorMapCommand(): invalid colormap!");
414     throw KERNEL::createSalomeException("MEDPresentation::getColorMapCommand(): invalid colormap!");
415   }
416   pushAndExecPyLine(oss.str());
417
418   selectFieldComponent(); // somehow PV keeps the LUT parameters of the previous presentation, so better reset this.
419 }
420
421 void
422 MEDPresentation::showObject()
423 {
424   std::ostringstream oss;
425   oss << _dispVar << " = pvs.Show(" << _objVar << ", " << getRenderViewVar() << ");";
426   pushAndExecPyLine(oss.str());
427 }
428
429 void
430 MEDPresentation::showScalarBar()
431 {
432   std::ostringstream oss;
433   oss << _dispVar <<  ".SetScalarBarVisibility(" << getRenderViewVar() << ", True);";
434   pushAndExecPyLine(oss.str());
435 }
436
437 void
438 MEDPresentation::colorBy(const std::string & fieldType)
439 {
440   std::ostringstream oss;
441   oss << "pvs.ColorBy(" << _dispVar << ", ('" << fieldType << "', '" << _fieldName << "'));";
442   pushAndExecPyLine(oss.str());
443 }
444
445 void
446 MEDPresentation::rescaleTransferFunction()
447 {
448   std::ostringstream oss;
449   switch(_sbRange)
450   {
451     case MEDCALC::SCALAR_BAR_ALL_TIMESTEPS:
452       oss << _dispVar << ".RescaleTransferFunctionToDataRangeOverTime();";
453       break;
454     case MEDCALC::SCALAR_BAR_CURRENT_TIMESTEP:
455       oss << _dispVar << ".RescaleTransferFunctionToDataRange(False);";
456       break;
457     default:
458       STDLOG("MEDPresentation::getRescaleCommand(): invalid range!");
459       throw KERNEL::createSalomeException("MEDPresentation::getRescaleCommand(): invalid range!");
460   }
461   pushAndExecPyLine(oss.str()); oss.str("");
462   // Get min-max
463   oss << _rangeVar << " = [" << _dispVar << ".LookupTable.RGBPoints[0], " << _dispVar << ".LookupTable.RGBPoints[-4]];";
464   pushAndExecPyLine(oss.str());
465
466   // Adapt scalar bar title
467   scalarBarTitle();
468 }
469
470
471
472 int
473 MEDPresentation::GeneratePythonId()
474 {
475   static int INIT_ID = 0;
476   return INIT_ID++;
477 }
478
479 void
480 MEDPresentation::activateView()
481 {
482   MEDPyLockWrapper lock;
483   pushAndExecPyLine("pvs.SetActiveView(" + getRenderViewVar() + ");");
484 }
485
486
487 std::string
488 MEDPresentation::paravisDump() const
489 {
490   using namespace std;
491   ostringstream oss;
492   for (vector<string>::const_iterator it=_pythonCmds.begin(); it != _pythonCmds.end(); ++it)
493     {
494       oss << (*it);
495       oss << "\n";
496     }
497   return oss.str();
498 }
499
500 /**
501  * Query all available component names for the field associated with this presentation.
502  * Fills in all the corresponding string properties:
503  *  - PROP_COMPONENT1
504  *  - PROP_COMPONENT2
505  *    etc...
506  *  and the number of components.
507  */
508 void
509 MEDPresentation::fillAvailableFieldComponents()
510 {
511   MEDPyLockWrapper lock;  // GIL!
512   std::string typ;
513
514   if(_pvFieldType == "CELLS") {
515       typ = "CellData";
516   }
517   else if (_pvFieldType == "POINTS") {
518       typ = "PointData";
519   }
520   else {
521       std::string msg("Unsupported spatial discretisation: " + _pvFieldType);
522       STDLOG(msg);
523       throw KERNEL::createSalomeException(msg.c_str());
524   }
525
526   std::ostringstream oss;
527   oss << "__nbCompo = " << _srcObjVar << "." << typ << ".GetArray('" <<  _fieldName << "').GetNumberOfComponents();";
528   execPyLine(oss.str());
529   PyObject* p_obj = getPythonObjectFromMain("__nbCompo");
530   long nbCompo;
531   if (p_obj && PyInt_Check(p_obj))
532     nbCompo = PyInt_AS_LONG(p_obj);
533   else
534     {
535       STDLOG("Unexpected Python error");
536       throw KERNEL::createSalomeException("Unexpected Python error");
537     }
538   setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, nbCompo);
539   for (long i = 0; i<nbCompo; i++)
540     {
541       std::ostringstream oss2;
542       oss2 << "__compo = " << _srcObjVar << "." << typ << ".GetArray('" <<  _fieldName << "').GetComponentName(" << i << ");";
543       execPyLine(oss2.str());
544       PyObject* p_obj = getPythonObjectFromMain("__compo");
545       std::string compo;
546       if (p_obj && PyString_Check(p_obj))
547         compo = std::string(PyString_AsString(p_obj));  // pointing to internal Python memory, so make a copy!!
548       else
549         {
550           STDLOG("Unexpected Python error");
551           throw KERNEL::createSalomeException("Unexpected Python error");
552         }
553       std::ostringstream oss_p;
554       oss_p << MEDPresentation::PROP_COMPONENT << i;
555       setStringProperty(oss_p.str(), compo);
556     }
557 }
558
559 /**
560  * In case where a CELLS field needs to be converted to POINT field.
561  * This updates the source object to become the result of the CellDatatoPointData filter.
562  */
563 void
564 MEDPresentation::applyCellToPointIfNeeded()
565 {
566   if (_pvFieldType == "CELLS")
567     {
568       std::ostringstream oss, oss2;
569       // Apply Cell data to point data:
570       oss2 << "__srcObj" << GeneratePythonId();
571       oss << oss2.str() << " = pvs.CellDatatoPointData(Input=" << _srcObjVar << ");";
572       pushAndExecPyLine(oss.str()); oss.str("");
573       // Now the source becomes the result of the CellDatatoPointData:
574       _srcObjVar = oss2.str();
575     }
576 }
577
578 ///**
579 // * Convert a vector field into a 3D vector field:
580 // *  - if the vector field is already 3D, nothing to do
581 // *  - if it is 2D, then add a null component
582 // *  - otherwise (tensor field, scalar field) throw
583 // */
584 //void
585 //MEDPresentation::convertTo3DVectorField()
586 //{
587 //  std::ostringstream oss, oss1, oss2, oss3;
588 //
589 //  int nbCompo = getIntProperty(MEDPresentation::PROP_NB_COMPONENTS);
590 //  if (nbCompo < 2 || nbCompo > 3)
591 //    {
592 //      oss << "The field '" << _fieldName << "' must have 2 or 3 components for this presentation!";
593 //      STDLOG(oss.str());
594 //      throw KERNEL::createSalomeException(oss.str().c_str());
595 //    }
596 //  if (nbCompo == 3)
597 //    return;
598 //
599 //  // Apply calculator:
600 //  oss2 << "__srcObj" << GeneratePythonId();
601 //  oss << oss2.str() << " = pvs.Calculator(Input=" << _srcObjVar << ");";
602 //  pushAndExecPyLine(oss.str()); oss.str("");
603 //  // Now the source becomes the result of the CellDatatoPointData:
604 //  _srcObjVar = oss2.str();
605 //  std::string typ;
606 //  if(_pvFieldType == "CELLS")
607 //    typ = "Cell Data";
608 //  else if(_pvFieldType == "POINTS")
609 //    typ = "Point Data";
610 //  else
611 //    {
612 //      oss3 << "Field '" << _fieldName << "' has invalid field type";
613 //      STDLOG(oss3.str());
614 //      throw KERNEL::createSalomeException(oss3.str().c_str());
615 //    }
616 //  oss << _srcObjVar << ".AttributeMode = '" <<  typ << "';";
617 //  pushAndExecPyLine(oss.str()); oss.str("");
618 //  oss << _srcObjVar << ".ResultArrayName = '" <<  _fieldName << "_CALC';";  // will never be needed I think
619 //  pushAndExecPyLine(oss.str()); oss.str("");
620 //  oss << _srcObjVar << ".Function = '" <<  _fieldName << "_0*iHat + " << _fieldName << "_1*jHat + 0.0*zHat';";
621 //  pushAndExecPyLine(oss.str()); oss.str("");
622 //}
623