Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions kivy_matplotlib_widget/tools/clipboard_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

manage windows, linux (via xclip) and MacOS platform

not functionnal with Android platform
not functionnal with Android platform
(need to do something similar as kivy\core\clipboard\clipboard_android.py)

Note: A new image clipboard is be planned in kivy 3.0.0
Expand All @@ -25,37 +25,37 @@
"""
import subprocess
import tempfile

elif platform == 'macosx':
"""
Appkit come with pyobjc
"""
from AppKit import NSPasteboard, NSPasteboardTypePNG
from Foundation import NSData


def image2clipboard(widget):

if platform == 'win':
if platform == 'win':
def send_to_clipboard(clip_type, data):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(clip_type, data)
win32clipboard.CloseClipboard()

img = widget.export_as_image() #export widget as image
pil_img = PILImage.frombytes('RGBA',
img.texture.size,
img.texture.pixels)

output = BytesIO()
pil_img.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()
send_to_clipboard(win32clipboard.CF_DIB, data)
output.close()
send_to_clipboard(win32clipboard.CF_DIB, data)

elif platform == 'linux':

elif platform == 'linux':

def _copy_linux_xclip(image):
"""On Linux, copy the `image` to the clipboard. The `image` arg can either be
a PIL.Image.Image object or a str/Path refering to an image file.
Expand All @@ -71,18 +71,18 @@ def _copy_linux_xclip(image):
img.texture.pixels)
_copy_linux_xclip(pil_img)

elif platform == 'macosx':
elif platform == 'macosx':
img = widget.export_as_image() #export widget as image
pil_img = PILImage.frombytes('RGBA',
img.texture.size,
img.texture.pixels)
output = BytesIO()
pil_img.save(output, format="PNG")
data = output.getvalue()
output.close()
output.close()

image_data = NSData.dataWithBytes_length_(data, len(data))

pasteboard = NSPasteboard.generalPasteboard()
format_type = NSPasteboardTypePNG
pasteboard.clearContents()
Expand Down
10 changes: 5 additions & 5 deletions kivy_matplotlib_widget/tools/cursors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This file is based on mplcursors project. Some changes as been made to
"""This file is based on mplcursors project. Some changes as been made to
worked with kivy and my project

mplcursors project
Expand Down Expand Up @@ -175,8 +175,8 @@ def add_highlight(self, artist, *args, **kwargs):
return hl

# def _on_select_event(self, event):


# if (not self._filter_mouse_event(event)
# # See _on_pick. (We only suppress selects, not deselects.)
# or event in self._suppressed_events):
Expand Down Expand Up @@ -210,7 +210,7 @@ def add_highlight(self, artist, *args, **kwargs):
# pass

def xy_event(self, event):

# Work around lack of support for twinned axes.
per_axes_event = {ax: _reassigned_axes_event(event, ax)
for ax in {artist.axes for artist in self.artists}}
Expand All @@ -232,7 +232,7 @@ def xy_event(self, event):
== (other.artist, tuple(other.target))
for other in self._selections)),
key=lambda pi: pi.dist, default=None)

if pi:
if event.compare_xdata:
min_distance=pi.dist
Expand Down
94 changes: 47 additions & 47 deletions kivy_matplotlib_widget/tools/interactive_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import multiprocessing as mp

import matplotlib.pyplot as plt

from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
Expand All @@ -26,16 +27,16 @@
KV = '''
Screen
figure_wgt:figure_wgt

BoxLayout:
orientation:'vertical'

canvas.before:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
size: self.size
KivyMatplotNavToolbar:
id:nav_bar
nav_icon:'all'
Expand All @@ -53,17 +54,17 @@
max_hover_rate:app.max_hover_rate
legend_do_scroll_x:app.legend_do_scroll_x
hist_range:app.hist_range
autoscale_tight:app.autoscale_tight
autoscale_tight:app.autoscale_tight

'''

KV3D = '''
Screen
figure_wgt_layout:figure_wgt_layout

BoxLayout:
orientation:'vertical'

canvas.before:
Color:
rgba: (1, 1, 1, 1)
Expand All @@ -86,18 +87,18 @@ class GraphApp(App):
show_cursor_data = BooleanProperty(True)
drag_legend = BooleanProperty(False)
legend_do_scroll_x = BooleanProperty(True)
max_hover_rate = NumericProperty(5/60,allownone=True)
max_hover_rate = NumericProperty(5/60,allownone=True)
fast_draw = BooleanProperty(False)
hist_range = BooleanProperty(True)
autoscale_tight = BooleanProperty(False)

def __init__(self,
def __init__(self,
figure,
show_cursor_data=True,
hover_widget=PlotlyHover,
compare_hover_widget=TagCompareHover,
compare_hover=False,
legend_instance=None,
legend_instance=None,
custom_handlers=None,
multi_legend=False,
drag_legend=False,
Expand All @@ -120,10 +121,10 @@ def __init__(self,
self.multi_legend=multi_legend
self.disable_interactive_legend=disable_interactive_legend
self.disable_hover=disable_hover

# print(self.figure.get())
super(GraphApp, self).__init__(**kwargs)

self.drag_legend=drag_legend
self.show_cursor_data=show_cursor_data
self.compare_hover=compare_hover
Expand All @@ -134,50 +135,50 @@ def __init__(self,
self.autoscale_tight=autoscale_tight
self.register_cursor=register_cursor
self.figsize=figsize

def build(self):
if self.figsize:
Window.size = self.figsize

# Set minimum window size
Window.minimum_width, Window.minimum_height = (200, 200)

self.screen=Builder.load_string(KV)
return self.screen

def on_start(self, *args):
def on_start(self, *args):
if hasattr(self.figure,'get'):
figure = self.figure.get()[0]
else:
figure= self.figure

if isinstance(figure,list):
self.screen.figure_wgt.figure = figure[0]

else:
self.screen.figure_wgt.figure = figure

if self.register_cursor:
self.screen.figure_wgt.register_cursor(pickables=self.register_cursor)

if self.compare_hover:
if self.compare_hover_widget:
add_hover(self.screen.figure_wgt,mode='desktop',hover_type='compare',hover_widget=self.compare_hover_widget())
else:
add_hover(self.screen.figure_wgt,mode='desktop',hover_type='compare')

if not self.disable_hover:
if self.hover_widget:
add_hover(self.screen.figure_wgt,mode='desktop',hover_widget=self.hover_widget())
else:
add_hover(self.screen.figure_wgt,mode='desktop')
add_minmax(self.screen.figure_wgt)

if not self.disable_interactive_legend:
if len(self.screen.figure_wgt.figure.axes) > 0 and \
(self.screen.figure_wgt.figure.axes[0].get_legend() or \
self.legend_instance):

if self.multi_legend:
for i,current_legend_instance in enumerate(self.legend_instance):
if i==0:
Expand All @@ -188,47 +189,47 @@ def on_start(self, *args):
MatplotlibInteractiveLegend(self.screen.figure_wgt,
legend_instance=current_legend_instance,
custom_handlers=self.custom_handlers[i],
multi_legend=True)
else:
multi_legend=True)

else:
MatplotlibInteractiveLegend(self.screen.figure_wgt,
legend_instance=self.legend_instance,
custom_handlers=self.custom_handlers)

def app_window(plot_queue,**kwargs):

GraphApp(plot_queue,**kwargs).run()

class GraphApp3D(App):
figure = None
figsize = None #figure size in pixel. inpu is a tuple ex: (1200,400)

def __init__(self,
def __init__(self,
figure,
figsize=None,
**kwargs):
"""__init__ function class"""
self.figure=figure
self.figsize=figsize

# print(self.figure.get())
super(GraphApp3D, self).__init__(**kwargs)

def build(self):
if self.figsize:
Window.size = self.figsize

# Set minimum window size
Window.minimum_width, Window.minimum_height = (200, 200)
Window.minimum_width, Window.minimum_height = (200, 200)
self.screen=Builder.load_string(KV3D)
return self.screen

def on_start(self, *args):
def on_start(self, *args):
if hasattr(self.figure,'get'):
figure = self.figure.get()[0]
else:
figure= self.figure

if isinstance(figure,list):
self.screen.figure_wgt_layout.figure_wgt.figure = figure[0]

Expand All @@ -237,15 +238,15 @@ def on_start(self, *args):

def app_window_3D(plot_queue,**kwargs):

GraphApp3D(plot_queue,**kwargs).run()
GraphApp3D(plot_queue,**kwargs).run()

def interactive_graph(fig,**kwargs):
""" Interactive grpah using multiprocessing method.
""" Interactive grpah using multiprocessing method.
function need to be call in if __name__ == "__main__": method
"""
# Create a queue to pass the Matplotlib instance object
plot_queue = mp.Queue()

#switch to agg backend
plt.switch_backend('Agg')

Expand All @@ -255,20 +256,20 @@ def interactive_graph(fig,**kwargs):
# Create and start the subprocess
p = mp.Process(target=app_window, args=(plot_queue,), kwargs=kwargs)
p.start()

def interactive_graph_ipython(fig,**kwargs):
app_window(fig,**kwargs)

def interactive_graph3D_ipython(fig,**kwargs):
app_window_3D(fig,**kwargs)

def interactive_graph3D(fig,**kwargs):
""" Interactive grpah using multiprocessing method.
""" Interactive grpah using multiprocessing method.
function need to be call in if __name__ == "__main__": method
"""
# Create a queue to pass the Matplotlib instance object
plot_queue = mp.Queue()

#switch to agg backend
plt.switch_backend('Agg')

Expand All @@ -281,14 +282,13 @@ def interactive_graph3D(fig,**kwargs):

if __name__ == "__main__":
fig, ax1 = plt.subplots(1, 1)

line1, = ax1.plot([0,1,2,3,4], [1,2,8,9,4],label='line1')
line2, = ax1.plot([2,8,10,15], [15,0,2,4],label='line2')

ax1.legend()

interactive_graph(fig,show_cursor_data=False,drag_legend=True)

interactive_graph_ipython(fig,show_cursor_data=True)


Loading