#include <sstream>
+#if PY_VERSION_HEX < 0x03050000
+static char*
+Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
+{
+ return _Py_wchar2char(text, error_pos);
+}
+#endif
+
const std::string MEDPresentation::PROP_NAME = "name";
const std::string MEDPresentation::PROP_NB_COMPONENTS = "nbComponents";
const std::string MEDPresentation::PROP_SELECTED_COMPONENT = "selectedComponent";
const std::string MEDPresentation::PROP_COLOR_MAP = "colorMap";
const std::string MEDPresentation::PROP_SCALAR_BAR_RANGE = "scalarBarRange";
-MEDPresentation::MEDPresentation(MEDPresentation::TypeID fieldHandlerId, const std::string& name,
+MEDPresentation::MEDPresentation(MEDPresentation::TypeID handlerId, const std::string& name,
const MEDCALC::ViewModeType viewMode,
const MEDCALC::ColorMapType colorMap,
const MEDCALC::ScalarBarRangeType sbRange)
- : _fieldHandlerId(fieldHandlerId), _propertiesStr(),
- //_pipeline(0), _display(0)
+ : _handlerId(handlerId), _propertiesStr(),
+ _mcFieldType(MEDCoupling::ON_CELLS),
+ _pvFieldType(""), _meshName(""), _fieldName(""), _fileName(""),
_selectedComponentIndex(-1),
_viewMode(viewMode),
_colorMap(colorMap),
_sbRange(sbRange),
- _renderViewPyId(-1), // will be set by getRenderViewCommand()
+ _renderViewPyId(-1), // will be set by MEDPresentationManager_i::_makePresentation()
_globalDict(0)
{
- MEDCALC::MEDDataManager_ptr dataManager(MEDFactoryClient::getDataManager());
- MEDCALC::FieldHandler* fieldHandler = dataManager->getFieldHandler(fieldHandlerId);
- MEDCALC::MeshHandler* meshHandler = dataManager->getMesh(fieldHandler->meshid);
- MEDCALC::DatasourceHandler* dataSHandler = dataManager->getDatasourceHandlerFromID(meshHandler->sourceid);
-
- _fileName = dataSHandler->uri;
- _fieldName = fieldHandler->fieldname;
- _fieldType = getFieldTypeString((MEDCoupling::TypeOfField) fieldHandler->type);
- _meshName = meshHandler->name;
-
- if (_fileName.substr(0, 7) != std::string("file://")) {
- const char* msg = "MEDPresentation(): Data source is not a file! Can not proceed.";
- STDLOG(msg);
- throw MEDPresentationException(msg);
- }
- _fileName = _fileName.substr(7, _fileName.size());
-
setStringProperty(MEDPresentation::PROP_NAME, name);
setIntProperty(MEDPresentation::PROP_NB_COMPONENTS, 0);
// Python variables:
int id = GeneratePythonId();
- std::ostringstream oss_o, oss_d, oss_l, oss_s;
+ std::ostringstream oss_o, oss_d, oss_l, oss_s, oss_r;
oss_o << "__obj" << id;
oss_s << "__srcObj" << id;
oss_d << "__disp" << id;
oss_l << "__lut" << id;
+ oss_r << "__range" << id;
_objVar = oss_o.str();
_srcObjVar = oss_s.str();
_dispVar = oss_d.str();
_lutVar = oss_l.str();
+ _rangeVar = oss_r.str();
+}
+
+/**
+ * For most of the presentations the field name etc is required.
+ * For the MEDPresentationMeshView however, the handler ID is a mesh handler ID, not a field, and the
+ * treatment is specific.
+ */
+void
+MEDPresentation::initFieldMeshInfos()
+{
+ MEDCALC::MEDDataManager_ptr dataManager(MEDFactoryClient::getDataManager());
+ MEDCALC::FieldHandler* fieldHandler = dataManager->getFieldHandler(_handlerId);
+ MEDCALC::MeshHandler* meshHandler = dataManager->getMeshHandler(fieldHandler->meshid);
+ MEDCALC::DatasourceHandler* dataSHandler = dataManager->getDatasourceHandlerFromID(meshHandler->sourceid);
+
+ extractFileName(std::string(dataSHandler->uri));
+
+ _fieldName = fieldHandler->fieldname;
+ _mcFieldType = (MEDCoupling::TypeOfField) fieldHandler->type;
+ _pvFieldType = getPVFieldTypeString(_mcFieldType);
+ _colorByType = _pvFieldType; // by default the same; overridden in DeflectionShape, VectorField, PointSprite and Contour
+ _meshName = meshHandler->name;
+}
+
+void
+MEDPresentation::extractFileName(const std::string& name)
+{
+ _fileName = name;
+ if (_fileName.substr(0, 7) != std::string("file://")) {
+ const char* msg = "MEDPresentation(): Data source is not a file! Can not proceed.";
+ STDLOG(msg);
+ throw MEDPresentationException(msg);
+ }
+ _fileName = _fileName.substr(7, _fileName.size());
}
MEDPresentation::~MEDPresentation()
STDLOG("~MEDPresentation(): clear display");
{
MEDPyLockWrapper lock;
- std::ostringstream oss_v, oss;
- oss_v << "__view" << _renderViewPyId;
- oss << "pvs.Hide(" << _objVar << ", view=" << oss_v.str() << ");";
- oss << "pvs.Render();";
-
- PyRun_SimpleString(oss.str().c_str());
+ std::ostringstream oss;
+
+ oss << "pvs.Hide(" << _objVar << ", view=" << getRenderViewVar() << ");";
+ execPyLine(oss.str());
+ // :TRICKY: The two following lines raise an exception when closing MED module
+ // after sequence: MED - load file - PARAVIS - MED - close SALOME
+ // (see Mantis #23461)
+ //execPyLine(getRenderViewVar() + ".ResetCamera();");
+ //execPyLine("pvs.Render();");
}
}
{
MEDPyLockWrapper lock;
pushAndExecPyLine( "import pvsimple as pvs;");
+ pushAndExecPyLine( "import medcalc");
}
}
std::string
-MEDPresentation::getFieldTypeString(MEDCoupling::TypeOfField fieldType) const
+MEDPresentation::getPVFieldTypeString(MEDCoupling::TypeOfField fieldType) const
{
switch(fieldType)
{
return "CELLS";
case MEDCoupling::ON_NODES:
return "POINTS";
+ case MEDCoupling::ON_GAUSS_PT:
+ return "POINTS"; // because internally after application of the ELGA filter, the field will appear as a POINT field
+ case MEDCoupling::ON_GAUSS_NE:
+ return "POINTS"; // because internally after application of the ELNO mesh filter, the field will appear as a POINT field
default:
- STDLOG("MEDPresentation::getFieldTypeString() -- Not implemented ! Gauss points?");
+ STDLOG("MEDPresentation::getPVFieldTypeString() -- Not implemented ! ELNO field?");
return "";
}
}
return oss.str();
}
+/*!
+ * Creates the MEDReader source in the pipeline, and potentially apply GAUSS/ELNO filters.
+ */
void
MEDPresentation::createSource()
{
+ std::string typ;
+ switch(_mcFieldType) {
+ case MEDCoupling::ON_CELLS: typ = "P0"; break;
+ case MEDCoupling::ON_NODES: typ = "P1"; break;
+ case MEDCoupling::ON_GAUSS_PT: typ = "GAUSS"; break;
+ case MEDCoupling::ON_GAUSS_NE: typ = "GSSNE"; break;
+ default:
+ const char * msg ="MEDPresentation::createSource(): field type not impl. yet!";
+ STDLOG(msg);
+ throw KERNEL::createSalomeException(msg);
+ }
+
std::ostringstream oss;
oss << _srcObjVar << " = pvs.MEDReader(FileName='" << _fileName << "');";
pushAndExecPyLine(oss.str()); oss.str("");
+ oss << "medcalc.SelectSourceField(" << _srcObjVar << ", '" << _meshName << "', '"
+ << _fieldName << "', '" << typ << "');";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ // Generate complete vector fields: fields with 2 components will copied into <name>_vector and
+ // have a third null component added.
oss << _srcObjVar << ".GenerateVectors = 1;";
pushAndExecPyLine(oss.str()); oss.str("");
+
+ // Make sure this is set so we stick to time steps:
+ pushAndExecPyLine("pvs.GetAnimationScene().PlayMode = 'Snap To TimeSteps'");
+
+ // Deal with GAUSS fields:
+ if(_mcFieldType == MEDCoupling::ON_GAUSS_PT)
+ {
+ std::ostringstream oss, oss2;
+ oss2 << "__srcObj" << GeneratePythonId();
+ oss << oss2.str() << " = pvs.GaussPoints(Input=" << _srcObjVar << ");";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ // Now the source becomes the result of the CellDatatoPointData:
+ _srcObjVar = oss2.str();
+ oss << _srcObjVar << ".SelectSourceArray = ['CELLS', 'ELGA@0'];";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ }
+ if(_mcFieldType == MEDCoupling::ON_GAUSS_NE)
+ {
+ std::ostringstream oss, oss2;
+ oss2 << "__srcObj" << GeneratePythonId();
+ oss << oss2.str() << " = pvs.ELNOMesh(Input=" << _srcObjVar << ");";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ // Now the source becomes the result of the CellDatatoPointData:
+ _srcObjVar = oss2.str();
+ }
}
void
pushAndExecPyLine(oss2.str()); oss2.str("");
if (_viewMode == MEDCALC::VIEW_MODE_OVERLAP) {
// this might potentially re-assign to an existing view variable, but this is OK, we
- // normally reassign exaclty the same RenderView object.
+ // normally reassign exactly the same RenderView object.
oss2 << view << " = pvs.GetActiveViewOrCreate('RenderView');";
pushAndExecPyLine(oss2.str()); oss2.str("");
} else if (_viewMode == MEDCALC::VIEW_MODE_REPLACE) {
}
}
+/**
+ * Needs the LUT, so to be called after selectColorMap for the first time.
+ */
+void
+MEDPresentation::scalarBarTitle()
+{
+ // get selected component name:
+ std::string compoName;
+ if (_selectedComponentIndex != -1)
+ {
+ std::ostringstream oss1;
+ oss1 << MEDPresentation::PROP_COMPONENT << _selectedComponentIndex;
+ compoName = getStringProperty(oss1.str());
+ }
+ else
+ {
+ if (getIntProperty(MEDPresentation::PROP_NB_COMPONENTS) == 1)
+ compoName = "";
+ else
+ compoName = "Magnitude";
+ }
+ std::ostringstream oss;
+ oss << "pvs.GetScalarBar(" << _lutVar << ").ComponentTitle = '" << compoName << "';";
+ pushAndExecPyLine(oss.str()); oss.str("");
+}
+
void
MEDPresentation::selectColorMap()
{
throw KERNEL::createSalomeException("MEDPresentation::getColorMapCommand(): invalid colormap!");
}
pushAndExecPyLine(oss.str());
+
+ selectFieldComponent(); // somehow PV keeps the LUT parameters of the previous presentation, so better reset this.
}
void
}
void
-MEDPresentation::colorBy(const std::string & fieldType)
+MEDPresentation::colorBy()
{
std::ostringstream oss;
- oss << "pvs.ColorBy(" << _dispVar << ", ('" << fieldType << "', '" << _fieldName << "'));";
+ oss << "pvs.ColorBy(" << _dispVar << ", ('" << _colorByType << "', '" << _fieldName << "'));";
pushAndExecPyLine(oss.str());
}
void
MEDPresentation::rescaleTransferFunction()
{
- std::string ret;
+ std::ostringstream oss;
switch(_sbRange)
{
case MEDCALC::SCALAR_BAR_ALL_TIMESTEPS:
- ret = _dispVar + ".RescaleTransferFunctionToDataRangeOverTime();";
+ oss << _dispVar << ".RescaleTransferFunctionToDataRangeOverTime();";
break;
case MEDCALC::SCALAR_BAR_CURRENT_TIMESTEP:
- ret = _dispVar + ".RescaleTransferFunctionToDataRange(False);";
+ oss << _dispVar << ".RescaleTransferFunctionToDataRange(False);";
break;
default:
STDLOG("MEDPresentation::getRescaleCommand(): invalid range!");
throw KERNEL::createSalomeException("MEDPresentation::getRescaleCommand(): invalid range!");
}
- pushAndExecPyLine(ret);
+ pushAndExecPyLine(oss.str()); oss.str("");
+ // Get min-max
+ oss << _rangeVar << " = [" << _dispVar << ".LookupTable.RGBPoints[0], " << _dispVar << ".LookupTable.RGBPoints[-4]];";
+ pushAndExecPyLine(oss.str());
+
+ // Adapt scalar bar title
+ scalarBarTitle();
}
+
+
int
MEDPresentation::GeneratePythonId()
{
return INIT_ID++;
}
-void
+bool
MEDPresentation::activateView()
{
MEDPyLockWrapper lock;
- pushAndExecPyLine("pvs.SetActiveView(" + getRenderViewVar() + ");");
+
+ execPyLine("__alive = " + getRenderViewVar() + " in pvs.GetRenderViews()");
+ PyObject * obj = getPythonObjectFromMain("__alive");
+ bool alive = true;
+ if (obj && PyBool_Check(obj))
+ alive = (obj == Py_True);
+
+ if (alive)
+ // The view is still there,just activate it:
+ pushAndExecPyLine("pvs.SetActiveView(" + getRenderViewVar() + ");");
+ else
+ {
+ // The view disappeared, recreate it in a new layout. The transfer of the objects is to be done by the caller.
+ std::ostringstream oss;
+ oss << "pvs.servermanager.misc.ViewLayout(registrationGroup='layouts');";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ oss << getRenderViewVar() << " = pvs.CreateView('RenderView');";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ }
+ return alive;
}
+/**!
+ * Called when the view has been recreated (because the user closed it).
+ * All the objects and set up are re-shown in the new view (which is stored in the same Python variable).
+ */
+void
+MEDPresentation::recreateViewSetup()
+{
+ showObject();
+ colorBy();
+ showScalarBar();
+ selectColorMap();
+ rescaleTransferFunction();
+ resetCameraAndRender();
+}
std::string
MEDPresentation::paravisDump() const
MEDPyLockWrapper lock; // GIL!
std::string typ;
- if(_fieldType == "CELLS") {
+ if(_pvFieldType == "CELLS") {
typ = "CellData";
}
- else if (_fieldType == "POINTS") {
+ else if (_pvFieldType == "POINTS") {
typ = "PointData";
}
else {
- std::string msg("Unsupported spatial discretisation: " + _fieldType);
+ std::string msg("Unsupported spatial discretisation: " + _pvFieldType);
STDLOG(msg);
throw KERNEL::createSalomeException(msg.c_str());
}
execPyLine(oss.str());
PyObject* p_obj = getPythonObjectFromMain("__nbCompo");
long nbCompo;
- if (p_obj && PyInt_Check(p_obj))
- nbCompo = PyInt_AS_LONG(p_obj);
+ if (p_obj && PyLong_Check(p_obj))
+ nbCompo = PyLong_AS_LONG(p_obj);
else
{
STDLOG("Unexpected Python error");
execPyLine(oss2.str());
PyObject* p_obj = getPythonObjectFromMain("__compo");
std::string compo;
- if (p_obj && PyString_Check(p_obj))
- compo = std::string(PyString_AsString(p_obj)); // pointing to internal Python memory, so make a copy!!
+ if (p_obj && PyUnicode_Check(p_obj))
+ compo = std::string(Py_EncodeLocale(PyUnicode_AS_UNICODE(p_obj), NULL)); // pointing to internal Python memory, so make a copy!!
else
{
STDLOG("Unexpected Python error");
void
MEDPresentation::applyCellToPointIfNeeded()
{
- std::ostringstream oss, oss2;
- // Apply Cell data to point data:
- oss2 << "__srcObj" << GeneratePythonId();
- oss << oss2.str() << " = pvs.CellDatatoPointData(Input=" << _srcObjVar << ");";
- pushAndExecPyLine(oss.str()); oss.str("");
- // Now the source becomes the result of the CellDatatoPointData:
- _srcObjVar = oss2.str();
-}
-
-/**
- * Convert a vector field into a 3D vector field:
- * - if the vector field is already 3D, nothing to do
- * - if it is 2D, then add a null component
- * - otherwise (tensor field, scalar field) throw
- */
-void
-MEDPresentation::convertTo3DVectorField()
-{
- std::ostringstream oss, oss1, oss2, oss3;
-
- int nbCompo = getIntProperty(MEDPresentation::PROP_NB_COMPONENTS);
- if (nbCompo < 2 || nbCompo > 3)
- {
- oss << "The field '" << _fieldName << "' must have 2 or 3 components for this presentation!";
- STDLOG(oss.str());
- throw KERNEL::createSalomeException(oss.str().c_str());
- }
- if (nbCompo == 3)
- return;
-
- // Apply calculator:
- oss2 << "__srcObj" << GeneratePythonId();
- oss << oss2.str() << " = pvs.Calculator(Input=" << _srcObjVar << ");";
- pushAndExecPyLine(oss.str()); oss.str("");
- // Now the source becomes the result of the CellDatatoPointData:
- _srcObjVar = oss2.str();
- std::string typ;
- if(_fieldType == "CELLS")
- typ = "Cell Data";
- else if(_fieldType == "POINTS")
- typ = "Point Data";
- else
+ if (_pvFieldType == "CELLS")
{
- oss3 << "Field '" << _fieldName << "' has invalid field type";
- STDLOG(oss3.str());
- throw KERNEL::createSalomeException(oss3.str().c_str());
+ std::ostringstream oss, oss2;
+ // Apply Cell data to point data:
+ oss2 << "__srcObj" << GeneratePythonId();
+ oss << oss2.str() << " = pvs.CellDatatoPointData(Input=" << _srcObjVar << ");";
+ pushAndExecPyLine(oss.str()); oss.str("");
+ // Now the source becomes the result of the CellDatatoPointData:
+ _srcObjVar = oss2.str();
}
- oss << _srcObjVar << ".AttributeMode = '" << typ << "';";
- pushAndExecPyLine(oss.str()); oss.str("");
- oss << _srcObjVar << ".ResultArrayName = '" << _fieldName << "_CALC';"; // will never be needed I think
- pushAndExecPyLine(oss.str()); oss.str("");
- oss << _srcObjVar << ".Function = '" << _fieldName << "_0*iHat + " << _fieldName << "_1*jHat + 0.0*zHat';";
- pushAndExecPyLine(oss.str()); oss.str("");
}
-//double
-//MEDPresentation::computeCellAverageSize()
+///**
+// * Convert a vector field into a 3D vector field:
+// * - if the vector field is already 3D, nothing to do
+// * - if it is 2D, then add a null component
+// * - otherwise (tensor field, scalar field) throw
+// */
+//void
+//MEDPresentation::convertTo3DVectorField()
//{
-// std::ostringstream oss;
-// oss << "import MEDLoader;";
-// pushAndExecPyLine(oss.str()); oss.str("");
-// oss << "__mesh = MEDLoader.ReadMeshFromFile('" << _fileName << "', '" << _meshName << "');";
-// pushAndExecPyLine(oss.str()); oss.str("");
+// std::ostringstream oss, oss1, oss2, oss3;
+//
+// int nbCompo = getIntProperty(MEDPresentation::PROP_NB_COMPONENTS);
+// if (nbCompo < 2 || nbCompo > 3)
+// {
+// oss << "The field '" << _fieldName << "' must have 2 or 3 components for this presentation!";
+// STDLOG(oss.str());
+// throw KERNEL::createSalomeException(oss.str().c_str());
+// }
+// if (nbCompo == 3)
+// return;
//
-// oss << "__bb = __mesh.getBoundingBox()";
+// // Apply calculator:
+// oss2 << "__srcObj" << GeneratePythonId();
+// oss << oss2.str() << " = pvs.Calculator(Input=" << _srcObjVar << ");";
// pushAndExecPyLine(oss.str()); oss.str("");
-// oss << "__deltas = [x[1]-x[0] for x in __bb];";
+// // Now the source becomes the result of the CellDatatoPointData:
+// _srcObjVar = oss2.str();
+// std::string typ;
+// if(_pvFieldType == "CELLS")
+// typ = "Cell Data";
+// else if(_pvFieldType == "POINTS")
+// typ = "Point Data";
+// else
+// {
+// oss3 << "Field '" << _fieldName << "' has invalid field type";
+// STDLOG(oss3.str());
+// throw KERNEL::createSalomeException(oss3.str().c_str());
+// }
+// oss << _srcObjVar << ".AttributeMode = '" << typ << "';";
// pushAndExecPyLine(oss.str()); oss.str("");
-// oss << "__vol = reduce(lambda x,y:x*y, __deltas, 1.0);";
+// oss << _srcObjVar << ".ResultArrayName = '" << _fieldName << "_CALC';"; // will never be needed I think
// pushAndExecPyLine(oss.str()); oss.str("");
-// // Average cell size is the the n-th root of average volume of a cell, with n being the space dimension
-// oss << "__cellSize = (__vol/__mesh.getNumberOfCells())**(1.0/len(__bb));";
+// oss << _srcObjVar << ".Function = '" << _fieldName << "_0*iHat + " << _fieldName << "_1*jHat + 0.0*zHat';";
// pushAndExecPyLine(oss.str()); oss.str("");
-//
-// PyObject * pyObj = getPythonObjectFromMain("__cellSize");
-// bool err = false;
-// if (!pyObj || !PyFloat_Check(pyObj)) { /* nothing to do, err handler below */}
-// else {
-// double ret= PyFloat_AsDouble(pyObj);
-// if(!PyErr_Occurred())
-// return ret;
-// }
-// // From here, an error for sure.
-// const char * msg = "MEDPresentation::computeCellAverageSize(): Python error.";
-// STDLOG(msg);
-// throw KERNEL::createSalomeException(msg);
//}