0

I'm trying to plot a number of segments of a timeseries, let's say 5 segments. I want each segment to be plotted individually and one after another after a given input (key press)

For example, 1) plot first segment, 2) wait for input and only after my input 3) plot next segment. I need python to wait for an input (key press) before plotting the next segment.

I've manged to almost make it work, but on jupyter notebook all figures are displayed at once only after I input something for all the plots (i.e. 5 inputs)

segments = segments.iloc[0:5]   # reduced number for testing
list = []

for i in segments.itertuples(): # loop over df
    
    f, ax = plt.subplots()
    ax.plot(time, yy)           # plot timeseries
    plt.xlim([segments.start_time, segments.end_time]) # only show between limits
    plt.show()
    
    # get user input
    a = input()
    list.append(a) # add input to the list

I've been banging my head but haven't managed to solve this. Any suggestion on how to solve this issue?

Oiko
  • 139
  • 9

1 Answers1

1

I have one that works from adapting an example I had used before, but note that I don't use subplot here!:

import matplotlib.pyplot as plt
inp_ = []
for i in range(3):
    labels = ['part_1','part_2','part_3']
    pie_portions = [5,6,7]
    plt.pie(pie_portions,labels=labels,autopct = '%1.1f%%')
    plt.title(f'figure_no : {i+1}')
    plt.show()
    # get user input
    a = input()
    inp_.append(a) # add input to the list

If you use subplot, then you get what you are seeing where it waits to show them all at the end because the figure is only complete and available to display after the last subplot is specified. Otherwise it is blocked. The easiest solution is to switch away from using subplots, like in my block of code posted above.

If you needed it to absolutely work with subplot, you can in fact update the figure after, like so;

#Using subplots based on https://matplotlib.org/stable/gallery/pie_and_polar_charts/pie_demo2.html
import matplotlib.pyplot as plt


import numpy as np
def update_subplot():
  '''
  based on https://stackoverflow.com/a/36279629/8508004
  '''
  global fig, axs
  ax_list = axs.ravel()
  # ax_list[0] refers to the first subplot
  ax_list[1].imshow(np.random.randn(100, 100))
  #plt.draw()


# Some data
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

# Make figure and axes
fig, axs = plt.subplots(1, 3)

# A standard pie plot
axs[0].pie(fracs, labels=labels, autopct='%1.1f%%', shadow=True)
axs[1].axis('off') # based on https://stackoverflow.com/a/10035974/8508004
axs[2].axis('off')
plt.show()

import time
time.sleep(2)

update_subplot()
fig

However, if you run that, you'll see you get successive views with one plot and then two and the first (with just one of two subplots) stays around in the notebook output and so it is less than desirable.

Always best to provide a minimal reproducible example when posting your question. That way you get something close to what works for your case.


Also, it is a bad idea to use a built-in type as a name of variable. (list = []) It can lead to errors you aren't expecting later. Imagine you wanted to typecast a set back to a list later in your code example.

Compare:

list = []
my_set= {1,2,3}
a = list(my_set)

to

my_list = []
my_set= {1,2,3}
a = list(my_set)

The first will give TypeError: 'list' object is not callable.

Wayne
  • 6,607
  • 8
  • 36
  • 93
  • Thanks! It works perfectly. I also took your advice with naming variables. The only issue is that Jupyter Notebook does not show the plot when `%matplotlib notebook` is used. It online works when plotting `inline`. – Oiko Sep 13 '22 at 13:30
  • 1
    Lately I just take the default without setting `%matplotlib` anything. I think after some momentum with `%matplotlib notebook`, the shift has been back to not using that in general for the reasons you sort of found. In cases like what you want to do, it can get in the way. It's useful when you need that extra interface to provide options to the user, or for a savvy user to access those options, but not often now in general. So more about the modern `inline` handling [here](https://stackoverflow.com/a/73633497/8508004) for cases where you may still want to use `%matplotlib inline` for now. – Wayne Sep 13 '22 at 15:04