Commit 19b28455 authored by Locatelli's avatar Locatelli
Browse files

Add some stuff:

- Don't reset plot limits during an property event of data
parent eb3c26c3
INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/../NomadServer/src -I/usr/include/python3.5m -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtCore
bin_PROGRAMS = ploty2 mplplot offmplplot test test2
bin_PROGRAMS = ploty2 mplplot test test2
QT = \
view/qt/QtColorMapWidget.cpp \
......@@ -70,11 +70,13 @@ ploty2_SOURCES = \
manager/ServerRequesterManager.cpp \
manager/PlotManager.cpp \
manager/OffScreenPlotManager.cpp \
manager/mpl/MplEventManager.cpp \
$(PLOT) \
$(PROTOBUF) \
$(DATACONT) \
$(MPLCPP) \
$(QT)
$(QT) \
$(JSON)
ploty2_CPPFLAGS = $(RM_CXXFLAGS) -DOFFSCREEN -DTRACEDEBUG
ploty2_LDFLAGS = $(RM_LDFLAGS)
......@@ -87,6 +89,7 @@ mplplot_SOURCES = \
mainplot.cpp \
manager/ServerRequesterManager.cpp \
manager/ServerSubscriberManager.cpp \
manager/mpl/MplEventManager.cpp \
$(PLOT) \
$(PROTOBUF) \
$(DATACONT) \
......@@ -100,24 +103,6 @@ mplplot_LDADD = $(LIBS) $(RM_LIBS) \
$(BOOST_FILESYSTEM_LIB) \
$(BOOST_THREAD_LIB)
offmplplot_SOURCES = \
mainoffscreenplot.cpp \
manager/ServerRequesterManager.cpp \
manager/ServerSubscriberManager.cpp \
$(PLOT) \
$(PROTOBUF) \
$(DATACONT) \
$(MPLCPP) \
$(QT) \
$(JSON)
offmplplot_CPPFLAGS = $(RM_CXXFLAGS) -DOFFSCREEN -DTRACEDEBUG
offmplplot_LDFLAGS = $(RM_LDFLAGS)
offmplplot_LDADD = $(LIBS) $(RM_LIBS) \
$(BOOST_SYSTEM_LIB) \
$(BOOST_FILESYSTEM_LIB) \
$(BOOST_THREAD_LIB)
test_SOURCES = \
maintest.cpp
......
This diff is collapsed.
......@@ -40,6 +40,7 @@
#include "manager/ServerRequesterManager.h"
#include "view/qt/QtUpdateContainer.h"
#include "view/qt/QtUpdateThread.h"
#include "manager/mpl/MplEventManager.h"
using namespace std;
using namespace cameo;
......@@ -91,6 +92,8 @@ int32 main(int32 argc, char* argv[]) {
qRegisterMetaType<view::qt::QtUpdateContainer>();
// Create and init the Matplolib module
view::mpl::Mpl* mpl = new view::mpl::Mpl();
// Init the Mpl Event Manager
manager::mpl::MplEventManager::getInstance()->init(mpl);
// Init cameo application
int32 err = EXIT_SUCCESS;
......
......@@ -22,11 +22,14 @@
#include <fstream>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <thread>
#include "plot/Plot1D.h"
#include "plot/Plot2D.h"
#include "plot/offscreen/OffScreenEmptyPlot.h"
#include "plot/offscreen/OffScreenPlot1D.h"
#include "plot/offscreen/OffScreenPlot2D.h"
#include "common/protobuf/generated/NotificationMessages.pb.h"
#include "protobuf/generated/AcquisitionSerializer.pb.h"
#include "json/LogSender.h"
#include "Trace.h"
namespace manager {
......@@ -41,12 +44,16 @@ using namespace cameo;
* constructor
*/
OffScreenPlotManager::OffScreenPlotManager() {
m_Mpl = new view::mpl::Mpl();
m_Figure = new view::mpl::MplFigure();
}
/*
* constructor
*/
OffScreenPlotManager::~OffScreenPlotManager() {
delete m_Figure;
delete m_Mpl;
}
/*
......@@ -102,16 +109,81 @@ void OffScreenPlotManager::loop(application::Subscriber* subscriber) {
/*
* savePlot
*/
void OffScreenPlotManager::savePlot(const string& pbfilename, const std::string& path) {
// Start mplplot process with files name as arguments
vector<string> args;
args.push_back(pbfilename);
args.push_back(path);
shared_ptr<cameo::application::Instance> offplot = application::This::getServer().start("offmplplot", args);
if (!offplot->exists()) {
Error("OffScreenPlotManager","savePlot", "unable to start offmplplot cameo instance", *offplot);
void OffScreenPlotManager::savePlot(string pbfilename, string path) {
boost::filesystem::path pbfile = path;
pbfile /= pbfilename;
pbfile.replace_extension("pb");
DBGMSG("file : " << pbfile.string().c_str());
ifstream inputMessage(pbfile.string().c_str(), fstream::binary);
if (inputMessage.is_open() == false) {
Error("OffScreenPlotManager", "savePlot", "Failed to open temporary file which contains proto::PlotPropertyDataMessage", pbfilename);
} else {
uint32 size = (uint32) boost::filesystem::file_size(pbfile);
char buffer[size];
inputMessage.read(buffer, size);
buffer::Data data;
data.ParseFromArray(buffer, size);
DBGMSG("type = " << data.type());
DBGMSG("buffer = " << size);
DBGMSG("numor = " << data.numor());
DBGMSG("dataxArray = " << data.xdata_size());
DBGMSG("datayArray = " << data.ydata_size());
DBGMSG("datazArray = " << data.zdata_size());
inputMessage.close();
ostringstream plotkey;
plotkey << pbfilename;
if ((data.xdata_size() > 0) && (data.ydata_size() > 0) && (data.zdata_size() > 0)) {
// 2D
for (int32 i = 0; i < data.xdata_size(); ++i) {
try {
plot::offscreen::OffScreenPlot2D plot(m_Figure, plotkey.str(), m_Mpl, i, &data);
plot.display();
plot.save(pbfile.parent_path().parent_path().string());
} catch (Error& e) {
Error("OffScreenPlotManager", "savePlot", "Failed create 2d plot", plotkey.str());
}
}
} else if ((data.xdata_size() > 0) && (data.ydata_size() > 0)) {
// 1D
for (int32 i = 0; i < data.xdata_size(); ++i) {
try {
plot::offscreen::OffScreenPlot1D plot(m_Figure, plotkey.str(), m_Mpl, i, &data);
plot.display();
plot.save(pbfile.parent_path().parent_path().string());
} catch (Error& e) {
Error("OffScreenPlotManager", "savePlot", "Failed create 1d plot", plotkey.str());
}
}
} else {
try {
plot::offscreen::OffScreenEmptyPlot plot(m_Figure, plotkey.str(), m_Mpl, 0, &data);
plot.display();
plot.save(pbfile.parent_path().parent_path().string());
} catch (Error& e) {
Error("OffScreenPlotManager", "savePlot", "Failed create empty plot", plotkey.str());
}
}
// delete file
boost::filesystem::remove(pbfile);
if (data.type() == buffer::Data::Log) {
// Send image to log database system
json::LogSender sender(&data);
sender.postMessage();
boost::filesystem::path pngfile = path;
pngfile = pngfile.parent_path().parent_path();
pngfile /= pbfilename;
DBGMSG("remove -> " << pngfile.string());
// delete image file
boost::filesystem::remove(pngfile);
}
}
}
}
......@@ -21,7 +21,8 @@
#include <cameo/cameo.h>
#include "plot/Plot1D.h"
#include "view/mpl/Mpl.h"
#include "view/mpl/MplFigure.h"
namespace manager {
......@@ -46,7 +47,12 @@ public:
*/
void loop(cameo::application::Subscriber* subscriber);
void savePlot(const std::string& pbfilename, const std::string& path);
/*!
* \brief Optimization plot result creation
* \param[in] pbfilename the plot binary file name from server
* \param[in] path the path directory of the pb file
*/
void savePlot(std::string pbfilename, std::string path);
private:
......@@ -67,6 +73,8 @@ private:
static OffScreenPlotManager* m_Instance; //! Pointer of singleton instance
view::mpl::Mpl* m_Mpl; //! Mpl object (main class which managed the matplotib api)
view::mpl::MplFigure* m_Figure; //! Matplotlib Figure object
};
}
......
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
#include "MplEventManager.h"
#include "view/mpl/MplLock.h"
#include <boost/python/import.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
using namespace view::mpl;
namespace manager {
namespace mpl {
MplEventManager* MplEventManager::m_Instance = nullptr;
const char MplEventManager::MODULE_EVENT_NAME[] = "module_event";
/*
* constructor
*/
MplEventManager::MplEventManager() {
m_mpl = nullptr;
m_BypassXLimChanged = false;
m_BypassYLimChanged = false;
}
/*
* init
*/
void MplEventManager::init(view::mpl::Mpl* mpl) {
m_mpl = mpl;
MplLock lock;
try {
m_ModuleEvent = bp::import(bp::str(MODULE_EVENT_NAME));
} catch (...) {
throw Error("MplEventManager", "contructor", "Error when loading the event module");
}
}
/*
* resetInstance
*/
void MplEventManager::resetInstance() {
if (m_Instance != nullptr) {
m_Instance->reset();
delete m_Instance;
m_Instance = nullptr;
}
}
/*
* reset
*/
void MplEventManager::reset() {
}
/*
* getInstance
*/
MplEventManager* MplEventManager::getInstance() {
if (m_Instance == nullptr) {
m_Instance = new MplEventManager();
}
return m_Instance;
}
/*
* subscriberXLimChanged
*/
void MplEventManager::subscribeXLimChanged(bp::object* obj, MplEventSubscriber* subscriber) throw (Error) {
unique_lock<recursive_mutex> lock(m_XLimChangedMutex);
if (m_XLimChangedSubcribers.find(obj) == m_XLimChangedSubcribers.end()) {
// Connect pick event
auto args = bp::make_tuple("xlim_changed", m_ModuleEvent.attr("xlim_changed"));
uint32 eventid = bp::extract<uint32>(obj->attr("callbacks").attr("connect")(*args));
// Add to map
m_XLimChangedSubcribers[obj] = subscriber;
m_XLimChanged[obj] = eventid;
}
}
/*
* unsubscriberXLimChanged
*/
void MplEventManager::unsubscribeXLimChanged(bp::object* obj) throw (Error) {
unique_lock<recursive_mutex> lock(m_XLimChangedMutex);
// remove subscriber from map
if (m_XLimChangedSubcribers.find(obj) != m_XLimChangedSubcribers.end()) {
auto args = bp::make_tuple(m_XLimChanged[obj]);
obj->attr("callbacks").attr("disconnect")(*args);
m_XLimChangedSubcribers.erase(obj);
m_XLimChanged.erase(obj);
}
}
/*
* xlimChanged
*/
void MplEventManager::xlimChanged(PyObject *self, PyObject* event) {
if (m_BypassXLimChanged == true)
return;
unique_lock<recursive_mutex> lock(m_XLimChangedMutex);
// Event received, pass it to all subscriber
for (auto pe : m_XLimChangedSubcribers) {
try {
MplLock lock;
pe.second->treatEvent(MplEventSubscriber::XLIM_CHANGED);
} catch (Error& e) {
// Error , do nothing, a event is missed
}
}
}
/*
* subscriberYLimChanged
*/
void MplEventManager::subscribeYLimChanged(bp::object* obj, MplEventSubscriber* subscriber) throw (Error) {
unique_lock<recursive_mutex> lock(m_YLimChangedMutex);
if (m_YLimChangedSubcribers.find(obj) == m_YLimChangedSubcribers.end()) {
// Connect pick event
auto args = bp::make_tuple("ylim_changed", m_ModuleEvent.attr("ylim_changed"));
int32 eventid = bp::extract<int32>(obj->attr("callbacks").attr("connect")(*args));
// Add to map
m_YLimChangedSubcribers[obj] = subscriber;
m_YLimChanged[obj] = eventid;
}
}
/*
* unsubscriberYLimChanged
*/
void MplEventManager::unsubscribeYLimChanged(bp::object* obj) throw (Error) {
unique_lock<recursive_mutex> lock(m_YLimChangedMutex);
// remove subscriber from map
if (m_YLimChangedSubcribers.find(obj) != m_YLimChangedSubcribers.end()) {
auto args = bp::make_tuple(m_YLimChanged[obj]);
obj->attr("callbacks").attr("disconnect")(*args);
m_YLimChangedSubcribers.erase(obj);
m_YLimChanged.erase(obj);
}
}
/*
* ylimChanged
*/
void MplEventManager::ylimChanged(PyObject *self, PyObject* event) {
if (m_BypassYLimChanged == true)
return;
unique_lock<recursive_mutex> lock(m_YLimChangedMutex);
// Event received, pass it to all subscriber
for (auto pe : m_YLimChangedSubcribers) {
try {
MplLock lock;
pe.second->treatEvent(MplEventSubscriber::YLIM_CHANGED);
} catch (Error& e) {
// Error , do nothing, a event is missed
}
}
}
/*!
* \brief Static method poointer pass to python matplotlib
*/
static PyObject *xlim_changed_event(PyObject *self, PyObject *event) {
MplEventManager::getInstance()->xlimChanged(self, event);
Py_RETURN_NONE;
}
/*!
* \brief Static method poointer pass to python matplotlib
*/
static PyObject *ylim_changed_event(PyObject *self, PyObject *event) {
MplEventManager::getInstance()->ylimChanged(self, event);
Py_RETURN_NONE;
}
/*!
* \brief Contains list of event type
*/
static PyMethodDef events[] = { { "xlim_changed", xlim_changed_event, METH_O, NULL }, { "ylim_changed", ylim_changed_event,
METH_O, NULL }, { NULL, NULL, 0, NULL } };
/*!
* \brief Module event structure info
*/
static struct PyModuleDef moduleeventdef = {
PyModuleDef_HEAD_INIT, "module_event",
NULL, -1, events,
NULL,
NULL,
NULL,
NULL };
/*!
* \brief method called for creating the module event
*/
PyMODINIT_FUNC PyInit_module_event(void)
{
return PyModule_Create(&moduleeventdef);
}
}
}
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
#ifndef MPLEVENTMANAGER_H
#define MPLEVENTMANAGER_H
#include <common/base/BaseTypes.h>
#include <map>
#include <mutex>
#include "view/mpl/Mpl.h"
#include "MplEventSubscriber.h"
#include "Trace.h"
#include "Error.h"
namespace manager {
namespace mpl {
/*!
* \brief Manager of GUI user event
*/
class MplEventManager {
public:
/*!
* \brief get singleton instance
* \return instance
*/
static MplEventManager* getInstance();
/*!
* \brief init the Mpl object
* \param[in] mpl Mpl object
*/
void init(view::mpl::Mpl* mpl);
/*!
* \brief reset instance
*/
void resetInstance();
static const char MODULE_EVENT_NAME[]; //! Module event name to load
/*!
* \brief Subscribe to a xlim changed event
* \param[in] obj Python Object reference
* \param[in] subscriber The subscriber for this event
* \throws Error
*/
void subscribeXLimChanged(bp::object* obj, MplEventSubscriber* subscriber) throw (Error);
/*!
* \brief Unsubscribe to a xlim changed event
* \param[in] obj Python Object reference
*/
void unsubscribeXLimChanged(bp::object* obj) throw (Error);
/*!
* \brief Subscribe to a xlim changed event
* \param[in] self Python Object of module
* \param[in] event Python Object contains event info
*/
void xlimChanged(PyObject *self, PyObject* event);
/*!
* \brief bypass xlim changed event on
*/
void bypassXLimChanged() {
m_BypassXLimChanged = true;
}
/*!
* \brief bypass xlim changed event off
*/
void clearBypassXLimChanged() {
m_BypassXLimChanged = false;
}
/*!
* \brief Subscribe to a ylim changed event
* \param[in] obj Python Object reference
* \param[in] subscriber The subscriber for this event
* \throws Error
*/
void subscribeYLimChanged(bp::object* obj, MplEventSubscriber* subscriber) throw (Error);
/*!
* \brief Unsubscribe to a ylim changed event
* \param[in] obj Python Object reference
*/
void unsubscribeYLimChanged(bp::object* obj) throw (Error);
/*!
* \brief Subscribe to a ylim changed event
* \param[in] self Python Object of module
* \param[in] event Python Object contains event info
*/
void ylimChanged(PyObject *self, PyObject* event);
/*!
* \brief bypass ylim changed event on
*/
void bypassYLimChanged() {
m_BypassYLimChanged = true;
}
/*!
* \brief bypass ylim changed event off
*/
void clearBypassYLimChanged() {
m_BypassYLimChanged = false;
}
private:
/*!
* \brief constructor
*/
MplEventManager();
/*!
* \brief reset instance
*/
void reset();
static MplEventManager* m_Instance; //! Pointer of singleton instance
view::mpl::Mpl* m_mpl; //! Mpl object (python matplotlib)
bp::object m_ModuleEvent; // Custom Ploty2 module for getting mpl gui event
bool m_BypassXLimChanged; //! By pass xlim changed event flag
std::map<bp::object*, MplEventSubscriber*> m_XLimChangedSubcribers; //! Map of xlim changed event subscriber
std::map<bp::object*, int32> m_XLimChanged; //! Map of xlim changed event subscriber
std::recursive_mutex m_XLimChangedMutex; //! Mutex on the PickEvent Subcribers
bool m_BypassYLimChanged; //! By pass ylim changed event flag
std::map<bp::object*, MplEventSubscriber*> m_YLimChangedSubcribers; //! Map of ylim changed event subscriber
std::map<bp::object*, int32> m_YLimChanged; //! Map of ylim changed event subscriber
std::recursive_mutex m_YLimChangedMutex; //! Mutex on the PickEvent Subcribers
};
}
}