Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Instrument Control
Ploty2
Commits
19b28455
Commit
19b28455
authored
Jul 31, 2019
by
Locatelli
Browse files
Add some stuff:
- Don't reset plot limits during an property event of data
parent
eb3c26c3
Changes
33
Expand all
Hide whitespace changes
Inline
Side-by-side
src/Makefile.am
View file @
19b28455
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
...
...
src/Makefile.in
View file @
19b28455
This diff is collapsed.
Click to expand it.
src/mainplot.cpp
View file @
19b28455
...
...
@@ -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
;
...
...
src/manager/OffScreenPlotManager.cpp
View file @
19b28455
...
...
@@ -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
);
}
}
}
}
src/manager/OffScreenPlotManager.h
View file @
19b28455
...
...
@@ -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
};
}
...
...
src/manager/mpl/MplEventManager.cpp
0 → 100644
View file @
19b28455
/*
* 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
);
}
}
}
src/manager/mpl/MplEventManager.h
0 → 100644
View file @
19b28455
/*
* 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
};
}
}