Commit 8fe8cfcd authored by Locatelli's avatar Locatelli
Browse files

Add options:

- on/off grid
- on/off log
parent fb6e4d76
- recompute projections x and y min max values when zooming
\ No newline at end of file
icons/log.png

502 Bytes

......@@ -477,6 +477,51 @@ void MplEventManager::gridButtonEvent(PyObject *self, PyObject *event) {
}
}
/*
* subscribeLogButtonEvent
*/
void MplEventManager::subscribeLogButtonEvent(PyObject* obj, MplEventSubscriber* subscriber) throw (Error) {
unique_lock<recursive_mutex> lock(m_LogButtonEventMutex);
if (m_LogButtonEventSubcribers.find(obj) == m_LogButtonEventSubcribers.end()) {
int32 eventid = toolManagerConnect("tool_trigger_log");
// Add to map
m_LogButtonEventSubcribers[obj] = subscriber;
m_LogButtonEvents[obj] = eventid;
}
}
/*
* unsubscribeLogButtonEvent
*/
void MplEventManager::unsubscribeLogButtonEvent(PyObject* obj) throw (Error) {
unique_lock<recursive_mutex> lock(m_LogButtonEventMutex);
// remove subscriber from map
if (m_LogButtonEventSubcribers.find(obj) != m_LogButtonEventSubcribers.end()) {
toolManagerDisconnect(m_LogButtonEvents[obj]);
m_LogButtonEventSubcribers.erase(obj);
m_LogButtonEvents.erase(obj);
}
}
/*
* logButtonEvent
*/
void MplEventManager::logButtonEvent(PyObject *self, PyObject *event) {
unique_lock<recursive_mutex> lock(m_LogButtonEventMutex);
// Event received, pass it to all subscriber
for (auto pe : m_LogButtonEventSubcribers) {
try {
MplLock lock;
pe.second->treatEvent(event);
} catch (Error& e) {
// Error , do nothing, a event is missed
}
}
}
/*
* mplConnect
*/
......@@ -615,6 +660,14 @@ static PyObject *tool_trigger_grids(PyObject *self, PyObject *event) {
Py_RETURN_NONE;
}
/*!
* \brief Static method poointer pass to python matplotlib
*/
static PyObject *tool_trigger_log(PyObject *self, PyObject *event) {
MplEventManager::getInstance()->gridButtonEvent(self, event);
Py_RETURN_NONE;
}
/*!
* \brief Contains list of event type
*/
......@@ -628,6 +681,7 @@ static PyMethodDef events[] = {
{ "tool_trigger_back", tool_trigger_back, METH_O, NULL },
// { "tool_trigger_forward", tool_trigger_forward, METH_O, NULL },
{ "tool_trigger_grids", tool_trigger_grids, METH_O, NULL },
{ "tool_trigger_log", tool_trigger_log, METH_O, NULL },
{ NULL, NULL, 0, NULL }
};
......
......@@ -246,6 +246,26 @@ public:
*/
void gridButtonEvent(PyObject *self, PyObject* event);
/*!
* \brief Subscribe to a log button event
* \param[in] obj Python Object reference
* \param[in] subscriber The subscriber for this event
* \throws Error
*/
void subscribeLogButtonEvent(PyObject* obj, MplEventSubscriber* subscriber) throw (Error);
/*!
* \brief Unsubscribe to a log button event
* \param[in] eventname Name of message event
*/
void unsubscribeLogButtonEvent(PyObject* obj) throw (Error);
/*!
* \brief Subscribe to a log button event
* \param[in] self Python Object of module
* \param[in] event Python Object contains event info
*/
void logButtonEvent(PyObject *self, PyObject* event);
private:
......@@ -329,6 +349,10 @@ private:
std::map<PyObject* , int32> m_GridButtonEvents; //! Map of grid button tool bar event subscriber
std::recursive_mutex m_GridButtonEventMutex; //! Mutex on the grid button ToolBar Event Subcribers
std::map<PyObject* , MplEventSubscriber*> m_LogButtonEventSubcribers; //! Map of grid button tool bar event subscriber
std::map<PyObject* , int32> m_LogButtonEvents; //! Map of grid button tool bar event subscriber
std::recursive_mutex m_LogButtonEventMutex; //! Mutex on the grid button ToolBar Event Subcribers
};
......
......@@ -139,7 +139,7 @@ public:
void relim() throw (Error);
/*!
* \brief show or hidde the plot grid
* \brief show or hide the plot grid
* \param[in] show The grid state
* \throws Error
*/
......
......@@ -38,6 +38,7 @@ const char MplToolBar::BUTTON_ZOOM_NAME[] = "zoom";
const char MplToolBar::BUTTON_SUBPLOTS_NAME[] = "subplots";
const char MplToolBar::GROUP_TOOLS_NAME[] = "tools";
const char MplToolBar::BUTTON_GRIDS_NAME[] = "grids";
const char MplToolBar::BUTTON_LOG_NAME[] = "log";
const char MplToolBar::GROUP_IO_NAME[] = "io";
const char MplToolBar::BUTTON_SAVE_NAME[] = "save";
const char MplToolBar::BUTTON_HELP_NAME[] = "help";
......@@ -55,6 +56,7 @@ MplToolBar::MplToolBar(Mpl* mpl) :
m_DoubleButtonSelectionActivated = false;
m_MotionActivated = false;
m_GridsActivated = false;
m_LogActivated = false;
}
/*
......@@ -71,6 +73,7 @@ MplToolBar::~MplToolBar() {
MplEventManager::getInstance()->unsubscribeBackButtonEvent(m_Toolbar);
// MplEventManager::getInstance()->unsubscribeForwardButtonEvent(m_Toolbar);
MplEventManager::getInstance()->unsubscribeGridButtonEvent(m_Toolbar);
MplEventManager::getInstance()->unsubscribeLogButtonEvent(m_Toolbar);
MplEventManager::getInstance()->unsubscribeButtonPressEvent(m_Toolbar);
MplEventManager::getInstance()->unsubscribeButtonReleaseEvent(m_Toolbar);
MplEventManager::getInstance()->unsubscribeMotionNotifyEvent(m_Toolbar);
......@@ -125,7 +128,7 @@ void MplToolBar::init() throw (Error) {
res = PyObject_CallObject(PyObject_GetAttrString(m_Mpl->getFigCanvManToolManager(), "add_tool"), args);
Py_DECREF(args);
if (res == nullptr) {
throw Error("MplToolBar", "init", "Error when executing the add_tool method");
throw Error("MplToolBar", "init", "Error when executing the add_tool method for grids");
}
Py_DECREF(res);
args = PyTuple_New(6);
......@@ -138,7 +141,30 @@ void MplToolBar::init() throw (Error) {
res = PyObject_CallObject(PyObject_GetAttrString(m_Toolbar, "add_toolitem"), args);
Py_DECREF(args);
if (res == nullptr) {
throw Error("MplToolBar", "init", "Error when executing the add_toolitem method");
throw Error("MplToolBar", "init", "Error when executing the add_toolitem method for grids");
}
Py_DECREF(res);
// Log
args = PyTuple_New(2);
PyTuple_SetItem(args, 0, PyUnicode_FromString(BUTTON_LOG_NAME));
PyTuple_SetItem(args, 1, PyObject_GetAttrString(m_Mpl->getBackendTools(), "ToolBase"));
res = PyObject_CallObject(PyObject_GetAttrString(m_Mpl->getFigCanvManToolManager(), "add_tool"), args);
Py_DECREF(args);
if (res == nullptr) {
throw Error("MplToolBar", "init", "Error when executing the add_tool method for log");
}
Py_DECREF(res);
args = PyTuple_New(6);
PyTuple_SetItem(args, 0, PyUnicode_FromString(BUTTON_LOG_NAME));
PyTuple_SetItem(args, 1, PyUnicode_FromString(GROUP_TOOLS_NAME));
PyTuple_SetItem(args, 2, PyLong_FromLong(-1));
PyTuple_SetItem(args, 3, PyUnicode_FromString("/users/locatelli/nomad/ploty2/icons/log.png"));
PyTuple_SetItem(args, 4, PyUnicode_FromString("Logarithm axis"));
PyTuple_SetItem(args, 5, Py_True);
res = PyObject_CallObject(PyObject_GetAttrString(m_Toolbar, "add_toolitem"), args);
Py_DECREF(args);
if (res == nullptr) {
throw Error("MplToolBar", "init", "Error when executing the add_toolitem method for log");
}
Py_DECREF(res);
......@@ -151,6 +177,7 @@ void MplToolBar::init() throw (Error) {
MplEventManager::getInstance()->subscribeBackButtonEvent(m_Toolbar, this);
// MplEventManager::getInstance()->subscribeForwardButtonEvent(m_Toolbar, this);
MplEventManager::getInstance()->subscribeGridButtonEvent(m_Toolbar, this);
MplEventManager::getInstance()->subscribeLogButtonEvent(m_Toolbar, this);
MplEventManager::getInstance()->subscribeButtonPressEvent(m_Toolbar, this);
MplEventManager::getInstance()->subscribeButtonReleaseEvent(m_Toolbar, this);
......@@ -224,13 +251,21 @@ void MplToolBar::treatEvent(PyObject* event) throw (Error) {
}
} else if (name.find(BUTTON_GRIDS_NAME) != string::npos) {
try {
m_Plot->grid(!m_GridsActivated);
m_GridsActivated = !m_GridsActivated;
m_Plot->grid(m_GridsActivated);
m_Mpl->redraw();
}
catch (Error& e){
Error("MplToolBar", "treatEvent", "couldn't change grid state to", !m_GridsActivated);
}
} else if (name.find(BUTTON_LOG_NAME) != string::npos) {
try {
m_LogActivated = !m_LogActivated;
m_Plot->log(m_LogActivated);
}
catch (Error& e){
Error("MplToolBar", "treatEvent", "couldn't change log state to", !m_LogActivated);
}
}
} else if (string("MouseEvent").find(Py_TYPE(event)->tp_name) != string::npos) {
......
......@@ -87,6 +87,14 @@ public:
return m_GridsActivated;
}
/*!
* \brief Is grid is activated
* \return state of grid
*/
bool logActivated() const {
return m_LogActivated;
}
private:
Mpl* m_Mpl; //! Matplotlib python
......@@ -101,6 +109,7 @@ private:
bool m_DoubleButtonSelectionActivated; //! Mouse Double Click button is pressed
bool m_MotionActivated; //! Mouse motion is running
bool m_GridsActivated; //! State of the grids
bool m_LogActivated; //! State of the log
//! Groups and button names
static const char GROUP_NAVIGATION_NAME[];
......@@ -115,6 +124,7 @@ private:
static const char GROUP_TOOLS_NAME[];
static const char BUTTON_GRIDS_NAME[];
static const char BUTTON_LOG_NAME[];
static const char GROUP_IO_NAME[];
static const char BUTTON_SAVE_NAME[];
......
......@@ -100,11 +100,16 @@ void EmptyPlot::update(int32 id) {
void EmptyPlot::resetLimits() throw (Error) {
}
/*
* grid
*/
void EmptyPlot::grid(bool show) throw (Error) {
}
/*
* log
*/
void EmptyPlot::log(bool tolog) throw (Error) {
}
}
......@@ -71,6 +71,13 @@ public:
*/
virtual void grid(bool show) throw (Error);
/*!
* \brief show or hide the plot in log
* \param[in] tolog The log state
* \throws Error
*/
virtual void log(bool tolog) throw (Error);
private:
/*!
......
......@@ -69,12 +69,19 @@ public:
virtual void resetLimits() throw (Error) = 0;
/*!
* \brief show or hidde the plot grid
* \brief show or hide the plot grid
* \param[in] show The grid state
* \throws Error
*/
virtual void grid(bool show) throw (Error) = 0;
/*!
* \brief show or hide the plot in log
* \param[in] tolog The log state
* \throws Error
*/
virtual void log(bool tolog) throw (Error) = 0;
protected:
/*!
......
......@@ -23,6 +23,7 @@
#include <chrono>
#include <vector>
#include <algorithm>
#include <limits>
#include "PlotWindow.h"
#include "datacontainer/PropertyPlotDataContainer.h"
......@@ -129,75 +130,18 @@ void Plot1D::display() throw (Error) {
////
//// Get x and y arrays values
////
// INT32ARRAY and INT32ARRAY
if ((m_PlotXPropertyTypes[i] == "int32array") && (m_PlotYPropertyTypes[i] == "int32array")) {
vector<int32> plotx;
vector<int32> ploty;
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_PlotXIds[i], plotx);
copy(plotx.begin(), plotx.end(), back_inserter(m_PlotXArrays[i]));
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get x int32 array ", m_PlotXIds[i]);
}
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_PlotYIds[i], ploty);
copy(ploty.begin(), ploty.end(), back_inserter(m_PlotYArrays[i]));
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y int32 array ", m_PlotYIds[i]);
}
// FLOAT64ARRAY and FLOAT64ARRAY
} else if ((m_PlotXPropertyTypes[i] == "float64array") && (m_PlotYPropertyTypes[i] == "float64array")) {
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_PlotXIds[i], m_PlotXArrays[i]);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get x float64 array ", m_PlotXIds[i]);
}
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_PlotYIds[i], m_PlotYArrays[i]);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y float64 array ", m_PlotYIds[i]);
}
// INT32ARRAY and FLOAT64ARRAY
} else if ((m_PlotXPropertyTypes[i] == "int32array") && (m_PlotYPropertyTypes[i] == "float64array")) {
vector<int32> plotx;
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_PlotXIds[i], plotx);
copy(plotx.begin(), plotx.end(), back_inserter(m_PlotXArrays[i]));
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get x int32 array ", m_PlotXIds[i]);
}
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_PlotYIds[i], m_PlotYArrays[i]);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y float64 array ", m_PlotYIds[i]);
}
// FLOAT64ARRAY and INT32ARRAY
} else if ((m_PlotXPropertyTypes[i] == "float64array") && (m_PlotYPropertyTypes[i] == "int32array")) {
vector<int32> ploty;
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_PlotXIds[i], m_PlotXArrays[i]);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get x float64 array ", m_PlotXIds[i]);
}
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_PlotYIds[i], ploty);
copy(ploty.begin(), ploty.end(), back_inserter(m_PlotYArrays[i]));
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y int32 array ", m_PlotYIds[i]);
}
// EMPTY and FLOAT64ARRAY
} else if ((m_PlotXPropertyTypes[i].empty() == true) && (m_PlotYPropertyTypes[i] == "float64array")) {
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_PlotYIds[i], m_PlotYArrays[i]);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y float64 array ", m_PlotYIds[i]);
}
try {
getData(m_PlotXPropertyTypes[i], m_PlotXIds[i], m_PlotXArrays[i], false);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get x array ", m_PlotXIds[i]);
}
try {
getData(m_PlotYPropertyTypes[i], m_PlotYIds[i], m_PlotYArrays[i], true);
} catch (Error& e) {
Error("Plot1D", "display", "Failed to get y array ", m_PlotYIds[i]);
}
////
//// Set plot parameters
////
......@@ -308,6 +252,11 @@ void Plot1D::display() throw (Error) {
}
}
///////////////////////////////////////////////////////////////////////////////////////
//// reset limits
////
resetLimits();
///////////////////////////////////////////////////////////////////////////////////////
//// Subscribe on property events
////
......@@ -378,14 +327,11 @@ void Plot1D::update(int32 id) {
for (uint32 i = 0; i < m_PlotXIds.size(); ++i) {
if (m_PlotXIds[i] == id) {
idfound = true;
if (m_PlotXPropertyTypes[i] == "int32array") {
vector<int32> plotx;
ServerRequester::getInstance()->getInt32PropertyArray(id, plotx);
copy(plotx.begin(), plotx.end(), back_inserter(m_PlotXArrays[i]));
} else if (m_PlotXPropertyTypes[i] == "float64array") {
ServerRequester::getInstance()->getFloat64PropertyArray(id, m_PlotXArrays[i]);
} else {
break;
try {
getData(m_PlotXPropertyTypes[i], id, m_PlotXArrays[i], false);
}
catch(Error& e) {
Warning("Plot1D", "update", "Failed to get x data on plot number", i);
}
if (m_PlotXArrays[i].size() != m_PlotYArrays[i].size()) {
m_PlotXArraysChanged = true;
......@@ -420,14 +366,11 @@ void Plot1D::update(int32 id) {
for (uint32 i = 0; i < m_PlotYIds.size(); ++i) {
if (m_PlotYIds[i] == id) {
idfound = true;
if (m_PlotYPropertyTypes[i] == "int32array") {
vector<int32> ploty;
ServerRequester::getInstance()->getInt32PropertyArray(id, ploty);
m_PlotYArrays[i].assign(ploty.begin(), ploty.end());
} else if (m_PlotYPropertyTypes[i] == "float64array") {
ServerRequester::getInstance()->getFloat64PropertyArray(id, m_PlotYArrays[i]);
} else {
break;
try {
getData(m_PlotYPropertyTypes[i], id, m_PlotYArrays[i], true);
}
catch(Error& e) {
Warning("Plot1D", "update", "Failed to get y data on plot number", i);
}
if (m_PlotYArrays[i].size() != m_PlotXArrays[i].size()) {
m_PlotYArraysChanged = true;
......@@ -474,12 +417,42 @@ void Plot1D::update(int32 id) {
}
}
/*
* getData
*/
void Plot1D::getData(const std::string& datatype, int32 id, std::vector<float64>& data, bool canlog) throw (Error) {
if (datatype == "int32array") {
vector<int32> int32data;
ServerRequester::getInstance()->getInt32PropertyArray(id, int32data);
if ((m_PlotWindow->getPlotToolBar().logActivated() == true) && (canlog == true)) {
data.resize(int32data.size());
transform(int32data.begin(), int32data.end(), data.begin(), [](int32 value) { return log10(value);});
}
else {
data.clear();
copy(int32data.begin(), int32data.end(), back_inserter(data));
}
}
else if (datatype == "float64array") {
vector<float64> float64data;
ServerRequester::getInstance()->getFloat64PropertyArray(id, float64data);
if ((m_PlotWindow->getPlotToolBar().logActivated() == true) && (canlog == true)) {
data.resize(float64data.size());
transform(float64data.begin(), float64data.end(), data.begin(), [](float64 value) { return log10(value);});
}
else {
data.clear();
copy(float64data.begin(), float64data.end(), back_inserter(data));
}
}
}
/*
* resizeX
*/
void Plot1D::resizeX() throw (Error) {
float64 gxmin = INT32_MAX;
float64 gxmax = INT32_MIN;
float64 gxmin = numeric_limits<float64>::max();
float64 gxmax = numeric_limits<float64>::min();
for (uint32 i = 0; i < m_PlotXIds.size(); ++i) {
float64 min = *std::min_element(m_PlotXArrays[i].begin(), m_PlotXArrays[i].end());
float64 max = *std::max_element(m_PlotXArrays[i].begin(), m_PlotXArrays[i].end());
......@@ -497,8 +470,8 @@ void Plot1D::resizeX() throw (Error) {
* resizeY
*/
void Plot1D::resizeY() throw (Error) {
float64 gymin = INT32_MAX;
float64 gymax = INT32_MIN;
float64 gymin = numeric_limits<float64>::max();
float64 gymax = numeric_limits<float64>::min();
for (uint32 i = 0; i < m_PlotYIds.size(); ++i) {
float64 min = *std::min_element(m_PlotYArrays[i].begin(), m_PlotYArrays[i].end());
float64 max = *std::max_element(m_PlotYArrays[i].begin(), m_PlotYArrays[i].end());
......@@ -527,4 +500,14 @@ void Plot1D::grid(bool show) throw (Error) {
m_MplPlot1D.grid(show);
}
/*
* log
*/
void Plot1D::log(bool tolog) throw (Error) {
// Force redraw plots with log options or not
for (auto id : m_PlotYIds) {
update(id);
}
}
}
......@@ -74,6 +74,13 @@ public:
*/
virtual void grid(bool show) throw (Error);
/*!
* \brief show or hide the plot in log
* \param[in] tolog The log state
* \throws Error
*/
virtual void log(bool tolog) throw (Error);
private:
/*!
......@@ -93,6 +100,8 @@ private:
*/
void resizeY() throw (Error);
void getData(const std::string& datatype, int32 id, std::vector<float64>& data, bool canlog) throw (Error);
uint32 m_NbPlots; //! Number of plot lines
std::vector<int32> m_PlotXIds; //! List of plot X id
std::vector<std::string> m_PlotXPropertyTypes; //! List of plot X property types
......
......@@ -110,9 +110,10 @@ void Plot2D::display() throw (Error) {
}
try {
getDataX();
getDataY();
getDataZ();
getData(m_DataCont->dataXPropertyTypes[m_DataCont->dataXIds[0]], m_DataCont->dataXIds[0], m_datax, false);
getData(m_DataCont->dataYPropertyTypes[m_DataCont->dataYIds[0]], m_DataCont->dataYIds[0], m_datay, false);
getData(m_DataCont->dataZPropertyTypes[m_DataCont->dataZIds[0]], m_DataCont->dataZIds[0], m_dataz, true);
computeProjections();
}
catch(Error& e) {
throw Error("Plot2D", "display", "Failed to load server data");
......@@ -201,72 +202,39 @@ void Plot2D::subscribeUpdate() {
}
/*
* getDataX
* getData
*/
void Plot2D::getDataX() throw (Error) {
m_datax.clear();
if (m_DataCont->dataXPropertyTypes[m_DataCont->dataXIds[0]] == "int32array") {
vector<int32> plotx;
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_DataCont->dataXIds[0], plotx);
copy(plotx.begin(), plotx.end(), back_inserter(m_datax));
} catch (Error& e) {
Error("Plot2D", "display", "Failed to get x int32 array ", m_DataCont->dataXIds[0]);
void Plot2D::getData(const std::string& datatype, int32 id, std::vector<float64>& data, bool canlog) throw (Error) {
if (datatype == "int32array") {
vector<int32> int32data;
ServerRequester::getInstance()->getInt32PropertyArray(id, int32data);
if (m_PlotWindow->getPlotToolBar().logActivated() == true) {
data.resize(int32data.size());
transform(int32data.begin(), int32data.end(), data.begin(), [](int32 value) { return log10(value);});
}
}
else if (m_DataCont->dataXPropertyTypes[m_DataCont->dataXIds[0]] == "float64array") {
try {
ServerRequester::getInstance()->getFloat64PropertyArray(m_DataCont->dataXIds[0], m_datax);
} catch (Error& e) {
Error("Plot2D", "display", "Failed to get x float64 array ", m_DataCont->dataXIds[0]);
else {
data.clear();
copy(int32data.begin(), int32data.end(), back_inserter(data));
}
}
}
/*
* getDataY
*/
void Plot2D::getDataY() throw (Error) {
m_datay.clear();
if (m_DataCont->dataYPropertyTypes[m_DataCont->dataYIds[0]] == "int32array") {
vector<int32> ploty;
try {
ServerRequester::getInstance()->getInt32PropertyArray(m_DataCont->dataYIds[0], ploty);
copy(ploty.begin(), ploty.end(), back_inserter(m_datay));
} catch (Error& e) {
Error("Plot2D", "display", "Failed to get y int32 array ", m_DataCont->dataYIds[0]);
}