summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortiagocoutinho <tiagocoutinho@users.sourceforge.net>2012-07-10 15:58:39 +0000
committertiagocoutinho <tiagocoutinho@users.sourceforge.net>2012-07-10 15:58:39 +0000
commite30711b4835c56b5ed361828507610c76374c3c5 (patch)
treec663190e9ad47004a85825ce7a567a5d55f619a8
parent367bb413328f082eec2079b6c56b559ce068e4ae (diff)
fix plotting feature
git-svn-id: file:///home/cpascual/src/sdnongit/svnbck/sardana/share/Sardana/trunk@20879 c480fdf4-a248-4bb0-8e4a-34cd1ef68f4f
-rw-r--r--src/sardana/macroserver/macro.py25
-rw-r--r--src/sardana/macroserver/macros/examples/plotting.py24
-rw-r--r--src/sardana/macroserver/msdoor.py37
-rw-r--r--src/sardana/spock/ipython_00_10/genutils.py11
-rw-r--r--src/sardana/spock/ipython_00_11/genutils.py20
-rw-r--r--src/sardana/spock/spockms.py32
-rw-r--r--src/sardana/tango/macroserver/Door.py79
7 files changed, 186 insertions, 42 deletions
diff --git a/src/sardana/macroserver/macro.py b/src/sardana/macroserver/macro.py
index c330fed2..75a8be7b 100644
--- a/src/sardana/macroserver/macro.py
+++ b/src/sardana/macroserver/macro.py
@@ -696,12 +696,31 @@ class Macro(Logger):
def plot(self, *args, **kwargs):
"""**Macro API**.
Sends the plot command to the client using the 'RecordData' DevEncoded
- attribute. The data is encoded using the JSON -> BZ2 codec.
+ attribute. The data is encoded using the pickle -> BZ2 codec.
:param args: the plotting args
:param kwargs: the plotting keyword args"""
- data = dict(args=args, kwargs=kwargs)
- self.sendRecordData(data, codec='bz2_json_plot')
+ self.pyplot.plot(*args, **kwargs)
+# data = dict(args=args, kwargs=kwargs)
+# self.sendRecordData(data, codec='bz2_pickle_plot')
+
+ @property
+ @mAPI
+ def pylab(self):
+ try:
+ pylab = self._pylab
+ except AttributeError:
+ self._pylab = pylab = self.door.pylab
+ return pylab
+
+ @property
+ @mAPI
+ def pyplot(self):
+ try:
+ pyplot = self._pyplot
+ except AttributeError:
+ self._pyplot = pyplot = self.door.pyplot
+ return pyplot
@property
def data(self):
diff --git a/src/sardana/macroserver/macros/examples/plotting.py b/src/sardana/macroserver/macros/examples/plotting.py
new file mode 100644
index 00000000..e32237bf
--- /dev/null
+++ b/src/sardana/macroserver/macros/examples/plotting.py
@@ -0,0 +1,24 @@
+import math
+from numpy import linspace
+from scipy.integrate import quad
+from scipy.special import j0
+
+from sardana.macroserver.macro import macro
+
+def j0i(x):
+ """Integral form of J_0(x)"""
+ def integrand(phi):
+ return math.cos(x * math.sin(phi))
+ return (1.0/math.pi) * quad(integrand, 0, math.pi)[0]
+
+@macro()
+def J0_plot(self):
+ x = linspace(0, 20, 200)
+ y = j0(x)
+ x1 = x[::10]
+ y1 = map(j0i, x1)
+ self.pyplot.plot(x, y, label=r'$J_0(x)$') #
+ self.pyplot.plot(x1, y1, 'ro', label=r'$J_0^{integ}(x)$')
+ self.pyplot.title(r'Verify $J_0(x)=\frac{1}{\{pi}\int_0^{\pi}\cos(x \sin\phi)\,d\phi$')
+ self.pyplot.xlabel('$x$')
+ self.pyplot.legend()
diff --git a/src/sardana/macroserver/msdoor.py b/src/sardana/macroserver/msdoor.py
index 694462ad..03333cd6 100644
--- a/src/sardana/macroserver/msdoor.py
+++ b/src/sardana/macroserver/msdoor.py
@@ -114,6 +114,7 @@ class MSDoor(MSObject):
self._record_data = None
self._macro_proxy_cache = None
self._input_handler = BaseInputHandler()
+ self._pylab_handler = None
MSObject.__init__(self, **kwargs)
def get_type(self):
@@ -129,6 +130,40 @@ class MSDoor(MSObject):
running_macro = property(get_running_macro)
+ def set_pylab_handler(self, ph):
+ self._pylab_handler = ph
+
+ def get_pylab_handler(self):
+ return self._pylab_handler
+
+ pylab_handler = property(get_pylab_handler, set_pylab_handler)
+
+ def get_pylab(self):
+ ph = self.pylab_handler
+ if ph is None:
+ import matplotlib.pylab
+ ph = matplotlib.pylab
+ return ph
+
+ pylab = property(get_pylab)
+
+ def set_pyplot_handler(self, ph):
+ self._pyplot_handler = ph
+
+ def get_pyplot_handler(self):
+ return self._pyplot_handler
+
+ pyplot_handler = property(get_pyplot_handler, set_pyplot_handler)
+
+ def get_pyplot(self):
+ ph = self.pyplot_handler
+ if ph is None:
+ import matplotlib.pyplot
+ ph = matplotlib.pyplot
+ return ph
+
+ pyplot = property(get_pyplot)
+
def set_input_handler(self, ih):
self._input_handler = ih
@@ -164,7 +199,7 @@ class MSDoor(MSObject):
if macro is None:
macro = self
- input_data = dict(prompt=msg)
+ input_data = dict(prompt=msg, type='input')
input_data.update(kwargs)
data_type = kwargs['data_type']
is_seq = not isinstance(data_type, (str, unicode)) and \
diff --git a/src/sardana/spock/ipython_00_10/genutils.py b/src/sardana/spock/ipython_00_10/genutils.py
index 7fbc5514..9db26845 100644
--- a/src/sardana/spock/ipython_00_10/genutils.py
+++ b/src/sardana/spock/ipython_00_10/genutils.py
@@ -897,11 +897,6 @@ def init_magic(ip):
ip.set_hook('pre_prompt_hook', magic.spock_pre_prompt_hook)
def init_pre_spock(ip, macro_server, door):
-
- # initialize input handler as soon as possible
- import sardana.spock.inputhandler
- input_handler = sardana.spock.inputhandler.InputHandler()
-
so = IPython.ipstruct.Struct()
full_door_tg_name, door_tg_name, door_tg_alias = from_name_to_tango(door)
#macro_server = get_ms_for_door(door_tg_name)
@@ -960,7 +955,7 @@ def init_spock(ip, macro_server, door):
def start(user_ns=None):
- #if '-pylab' not in sys.argv: sys.argv.insert(1, '-pylab')
+ if '-pylab' not in sys.argv: sys.argv.insert(1, '-pylab')
if '-q4thread' not in sys.argv: sys.argv.insert(1, '-q4thread')
# Make sure the log level is changed to warning
@@ -998,6 +993,10 @@ def mainloop(shell=None, user_ns=None):
shell.mainloop()
def run(user_ns=None):
+ # initialize input handler as soon as possible
+ import sardana.spock.inputhandler
+ input_handler = sardana.spock.inputhandler.InputHandler()
+
try:
mainloop(user_ns=user_ns)
finally:
diff --git a/src/sardana/spock/ipython_00_11/genutils.py b/src/sardana/spock/ipython_00_11/genutils.py
index 31aad4fb..3388a375 100644
--- a/src/sardana/spock/ipython_00_11/genutils.py
+++ b/src/sardana/spock/ipython_00_11/genutils.py
@@ -815,11 +815,6 @@ def unload_ipython_extension(ipython):
pass
def load_config(config):
-
- # initialize input handler as soon as possible
- import sardana.spock.inputhandler
- input_handler = sardana.spock.inputhandler.InputHandler()
-
spockver = release.version
pyver = get_python_version()
ipyver = get_ipython_version()
@@ -931,6 +926,7 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
term_app = config.TerminalIPythonApp
term_app.display_banner = True
term_app.gui = gui_mode
+ term_app.pylab='qt'
#term_app.nosep = False
#term_app.classic = True
@@ -954,6 +950,11 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
ipython_widget.pylab = 'inline'
# ------------------------------------
+ # ConsoleWidget
+ # ------------------------------------
+ console_widget = config.ConsoleWidget
+
+ # ------------------------------------
# FrontendWidget
# ------------------------------------
frontend_widget = config.FrontendWidget
@@ -1033,6 +1034,12 @@ def mainloop(app=None, user_ns=None):
app = start(user_ns)
app.start()
+def prepare_input_handler():
+ # initialize input handler as soon as possible
+ import sardana.spock.inputhandler
+ input_handler = sardana.spock.inputhandler.InputHandler()
+
+
def prepare_cmdline(argv=None):
if argv is None:
argv = sys.argv
@@ -1080,7 +1087,8 @@ def run():
sys.exit(-1)
except exception.SpockMissingRecommended, recommended:
print str(recommended)
-
+
+ prepare_input_handler()
prepare_cmdline()
launch_new_instance()
diff --git a/src/sardana/spock/spockms.py b/src/sardana/spock/spockms.py
index 42eb04d8..2d8dcb62 100644
--- a/src/sardana/spock/spockms.py
+++ b/src/sardana/spock/spockms.py
@@ -438,23 +438,23 @@ class SpockBaseDoor(BaseDoor):
def processRecordData(self, data):
if data is None: return
data = data[1]
- if data['type'] == 'plot':
- func_name = data['type']
- data = data['data']
- args, kwargs = data['args'], data['kwargs']
- # json converts strings to unicode strings but in a function call
- # python demands that the kwargs keys be strings so we need to convert
- # in python 3k this will change since all strings will be unicode
- new_kwargs = {}
- for k,v in kwargs.iteritems():
- if type(k) is unicode: k = str(k)
- new_kwargs[k] = v
+ if data['type'] == 'function':
+ func_name = data['func_name']
+ args = data['args']
+ kwargs = data['kwargs']
+
+ members = func_name.split(".")
+ mod_list, fname = members[:-1], members[-1]
+ mod_name = ".".join(mod_list)
+ if mod_name:
+ mod = __import__(mod_name, fromlist=mod_list)
+ func = getattr(mod, fname)
+ else:
+ func = __builtins__[fname]
try:
- import pylab
- f = getattr(pylab, func_name)
- f(*args, **new_kwargs)
- except Exception,e:
- self.logReceived(self.Warning, ['Unable to plot:', str(e)])
+ func(*args, **kwargs)
+ except Exception as e:
+ self.logReceived(self.Warning, ['Unable to execute %s: ' % func_name, str(e)])
_RECORD_DATA_THRESOLD = 4*1024*1024 # 4Mb
diff --git a/src/sardana/tango/macroserver/Door.py b/src/sardana/tango/macroserver/Door.py
index fd9910b0..0b07a0fd 100644
--- a/src/sardana/tango/macroserver/Door.py
+++ b/src/sardana/tango/macroserver/Door.py
@@ -83,19 +83,68 @@ class TangoInputHandler(BaseInputHandler):
self._input_event.set()
def input_wait(self, timeout=None):
- if timeout is not None:
- start_time = time.time()
-
wait = self._input_event.wait(timeout)
-
- if timeout is not None:
- dt = time.time() - start_time
- if self._value is None and dt > timeout:
- if 'default_value' in self.input_data:
- self._value = dict(input=self.input_data['default_value'])
+ # if there was a timeout:
+ # - set the value to the default value (if one exists)
+ # - inform clients that timeout occured and they should not wait for
+ # user input anymore
+ if not self._input_event.is_set():
+ if 'default_value' in self.input_data:
+ self._value = dict(input=self.input_data['default_value'])
+ self.send_input_timeout()
self._input_event.clear()
return self._value
+ def send_input_timeout(self):
+ idata = self.input_data
+ input_data = dict(type="timeout", macro_id=idata['macro_id'])
+ if 'default_value' in idata:
+ input_data['default_value'] = idata['default_value']
+ input_data = json.dumps(input_data)
+ door = self._door
+ door.set_attribute(self._attr, value=input_data)
+
+
+class TangoPylabHandler(object):
+
+ def __init__(self, door, attr, format="bz2_pickle"):
+ self.door = door
+ self.attr = attr
+ self.format = format
+ self.func_call
+
+ def handle(self, func_name, *args, **kwargs):
+ codec = CodecFactory().getCodec(self.format)
+ data = dict(type='function', func_name=func_name, args=args, kwargs=kwargs)
+ event_value = codec.encode(('', data))
+ self.door.set_attribute(self.attr, value=event_value)
+
+ def __getattr__(self, name):
+ def f(*args, **kwargs):
+ full_name = "pylab." + name
+ return self.handle(full_name, *args, **kwargs)
+ f.__name__ = name
+ return f
+
+class TangoPyplotHandler(object):
+
+ def __init__(self, door, attr, format="bz2_pickle"):
+ self.door = door
+ self.attr = attr
+ self.format = format
+
+ def handle(self, func_name, *args, **kwargs):
+ codec = CodecFactory().getCodec(self.format)
+ data = dict(type='function', func_name=func_name, args=args, kwargs=kwargs)
+ event_value = codec.encode(('', data))
+ self.door.set_attribute(self.attr, value=event_value)
+
+ def __getattr__(self, name):
+ def f(*args, **kwargs):
+ full_name = "matplotlib.pyplot." + name
+ return self.handle(full_name, *args, **kwargs)
+ f.__name__ = name
+ return f
class Door(SardanaDevice):
@@ -175,11 +224,21 @@ class Door(SardanaDevice):
self.door = door = \
macro_server.create_element(type="Door", name=name,
full_name=full_name, id=self.Id)
- input_attr = self.get_device_attr().get_attr_by_name('Input')
self._setupLogHandlers(levels)
+ multi_attr = self.get_device_attr()
+
+ input_attr = multi_attr.get_attr_by_name('Input')
self._input_handler = ih = TangoInputHandler(self, input_attr)
door.set_input_handler(ih)
+
+ recorddata_attr = multi_attr.get_attr_by_name('RecordData')
+ self._pylab_handler = pylabh = TangoPylabHandler(self, recorddata_attr)
+ door.set_pylab_handler(pylabh)
+
+ self._pyplot_handler = pyploth = TangoPyplotHandler(self, recorddata_attr)
+ door.set_pyplot_handler(pyploth)
+
door.add_listener(self.on_door_changed)
def _setupLogHandlers(self, levels):