Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
UI for matplotlib
-
I new to Python/Pythonista, and I am wondering if it would be possible to have a UI to launch something I did in matplotlib. I want to be able to tap a button and launch the scatter plot. The scatter plot works without the UI, but I am having trouble getting the button to work. Here is the code I have so far:
import ui import matplotlib.pyplot as plt from random import choice, randint v = ui.load_view() v.present('sheet') def button_tapped(sender): show_walk() def fill_x_values(walk_length): x_values = [0] points = walk_length while len(x_values) < points: x_direction = choice([1, -1]) x_distance = choice([1, 2, 3, 4]) x_step = x_direction * x_distance next_x = x_values[-1] + x_step x_values.append(next_x) return x_values def fill_y_values(walk_length): y_values = [0] points = walk_length while len(y_values) < points: y_direction = choice([1, -1]) y_distance = choice([1, 2, 3, 4]) y_step = y_direction * y_distance next_y = y_values[-1] + y_step y_values.append(next_y) return y_values def show_walk(): walk_length = 50000 x_values = fill_x_values(walk_length) y_values = fill_x_values(walk_length) plt.scatter(x_values, y_values,c='red', edgecolor='none', alpha=0.2, s=7) plt.axes().get_xaxis().set_visible(False) plt.axes().get_yaxis().set_visible(False) plt.show() button = ui.Button() button.action = button_tapped
Do any of you see what I am doing wrong? If you need any more info from me, please let me know. Thanks in advance.
-
Hi @p_atrick
Welcome to Pythonista.While I'm not familiar with matplotlib, I can suggest a couple of points regarding the UI.
The lines...
v = ui.load_view() v.present('sheet')
...need to go towards the end of your code, after the function definitions like
def button_tapped(sender)
so that the UI can "see" these definitions before it is initialised. Presenting the view should be the last thing you do.I see you use
ui.load_view()
which will load a pyui file with the same name as your script. It might be easier to define your button entirely in the interface builder (including setting its action attribute).Currently your last two lines of code only create a button object but do not place it anywhere within the UI (and as your UI is already "presented" it cannot be added anyway). These lines are unnecessary if the button is defined in the pyui file.
Finally, I understand matplotlib draws things in the console, so you might not see anything on pressing the button unless you exit to the console.
I hope this is helpful!
-
This code will present a very basic button that will run the matplotlib stuff when pressed. No pyui file used here.
As I mentioned, the matplotlib graph appears in the console rather than the UI. You might need to use a different UI element to display a matplotlib graph (maybe a
ui.ImageView()
) but I'm not sure of the specifics as regards working with matplotlib.import ui import matplotlib.pyplot as plt from random import choice, randint def button_tapped(sender): button.title = "Tapped!" show_walk() def fill_x_values(walk_length): x_values = [0] points = walk_length while len(x_values) < points: x_direction = choice([1, -1]) x_distance = choice([1, 2, 3, 4]) x_step = x_direction * x_distance next_x = x_values[-1] + x_step x_values.append(next_x) return x_values def fill_y_values(walk_length): y_values = [0] points = walk_length while len(y_values) < points: y_direction = choice([1, -1]) y_distance = choice([1, 2, 3, 4]) y_step = y_direction * y_distance next_y = y_values[-1] + y_step y_values.append(next_y) return y_values def show_walk(): walk_length = 50000 x_values = fill_x_values(walk_length) y_values = fill_x_values(walk_length) plt.scatter(x_values, y_values,c='red', edgecolor='none', alpha=0.2, s=7) plt.axes().get_xaxis().set_visible(False) plt.axes().get_yaxis().set_visible(False) plt.show() button = ui.Button() button.present() button.title = "Press here!" button.action = button_tapped
-
see here for an example of a matplotlib interactive zooming plot. I am not entirely sure if this works in the latest pythonista versions (probably only for the 2.7 interpreter)
But the key to simple static plots is basically:
self.b.seek(0) plt.savefig(self.b,format='jpg',dpi=dpi) self.img_view.image = ui.Image.from_data(self.b.getvalue())
where
self.b
is aBytesIO
object, and dpi is a number which you can experiment with to trade off speed vs quality.Also, something like
plt.gcf().set_size_inches(self.width/dpi,self.height/dpi)
might be needed so the dpi values are meaningful.