0

I want to select some points from a plot. I am using event picking and I want to store the data points that I select to numpy array. There is no problem about selecting points. I will select them and I can see those points in output (by printing command in function). The problem is that I don't know how to save these selected points, so that I can use them later. I am using global variable, but noting is saved to them after selecting data points when I print them independently. These data points are added to an array for each click (I know this from print command in each function calling), but it seems that when I print the array myself, they are empty. Any help appreciated!

import numpy as np
import matplotlib.pyplot as plt


    x= np.random.rand(10, 100)
    y = np.random.rand(10, 100)
    # the selected data
    diy_pick_x = np.zeros(0)
    diy_pick_y = np.zeros(0)
    
    a= np.zeros(0)
    b = np.zeros(0)
    
    fig, ax = plt.subplots()
    col = ax.scatter(x, y, 0.3, picker=True)
    
    plt.xlabel('Wavelength '+r'[${\rm \AA}$]')
    plt.ylabel('Flux '+r'[${\rm 10^{-17} erg  s^{-1}  \AA^{-1}}$]')
    
    
    
    def onpick(event):
        global diy_pick_x,  diy_pick_y
        global a, b
        ind = event.ind
        print("onpick scatter:", ind, np.take(x, ind), np.take(y, ind))
        diy_pick_x = np.append(diy_pick_x, np.take(x, ind))
        diy_pick_y = np.append(diy_pick_y, np.take(y, ind))
        a=diy_pick_x
        print(diy_pick_x)
        print(diy_pick_y)
    
    fig.canvas.mpl_connect('pick_event', onpick)



When I print the array, this is the result:

    print(diy_pick_x)

    Out[6]: array([], dtype=float64)
ImajinDevon
  • 287
  • 1
  • 11
s.a
  • 9
  • 4
  • So, to clarify: when I run your code I can print the contents of diy_pick_x successfully if it is within the same run of the code. What you seem to be asking is how to save the data to a file and load it again? – Mandias Jul 02 '22 at 02:12
  • Are you sure? Do yo mean that when you print the array (like what I have done in my question in the last part) you can see that the points? – s.a Jul 02 '22 at 02:17
  • Yes, I added plt.show() after the code you provided to show the plot and pick some points, as well as print(diy_pick_x) to print the final content of the array. – Mandias Jul 02 '22 at 02:19
  • I still have the same problem. After selecting points and closing the plot, when I type the print command in the terminal, I get the same result as above. The array is empty! – s.a Jul 02 '22 at 02:22
  • Your program ends when you close the plot. This means any data generated is "lost" and will not be printable. You must have the print occur while the data is still in session, or save it in a file for later use. – Mandias Jul 02 '22 at 02:23
  • I tried it again, when the plot is still open, and the result does not change! – s.a Jul 02 '22 at 02:26
  • How exactly are you running the code? I have an IDE (Atom) through which the program file is executed. All commands are already entered (including the print statement), which results in the expected output. Also, running the file directly through the terminal works too. – Mandias Jul 02 '22 at 02:27
  • I run in Spyder 4. Print commands in the functions works well, but after finishing selecting data points, there is no array that include them. All arrays (like: diy_pick_x) are empty. I do not expect this, because they are global. – s.a Jul 02 '22 at 02:32
  • Even modifying the code as shown in the answer below does not help? – Mandias Jul 02 '22 at 02:35
  • I changed it but didn't help – s.a Jul 02 '22 at 02:36
  • It's possible that the version of Python that you're using is a factor. I have Python 3.9.5 – Mandias Jul 02 '22 at 02:38
  • Yes, you are right, changing the python version solved the problem! Thank you! – s.a Jul 02 '22 at 03:20
  • Glad that it helped. Please make it clear which version of python you were using before and which you are using now. This can help others solve their issue if they experience it too. – Mandias Jul 02 '22 at 04:29
  • Unfortunately, It only works with python 2.7 and not even with python 3.9 in my case – s.a Jul 02 '22 at 20:37

1 Answers1

0

As mentioned in the comments, updating Python addressed the issue.

Another method which may work is use list mutability instead of global numpy arrays. This method works because the original lists still exist, and we can change their content without changing the "id" of the original list. If we were to reassign the list like with "diy_pick_x = [new items]" then we are making a new list that happens to have the same name, but does not exist outside of the onpick function.

Reviewing objects in python that are mutable may help with understanding.

import matplotlib.pyplot as plt
import numpy as np

x = np.random.rand(10, 100)
y = np.random.rand(10, 100)
# the selected data
diy_pick_x = [0] # <----- Changed
diy_pick_y = [0] # <----- Changed

a = np.zeros(0)
b = np.zeros(0)

fig, ax = plt.subplots()
col = ax.scatter(x, y, 0.3, picker=True)

plt.xlabel("Wavelength " + r"[${\rm \AA}$]")
plt.ylabel("Flux " + r"[${\rm 10^{-17} erg  s^{-1}  \AA^{-1}}$]")
    
def onpick(event):
    global a, b
    ind = event.ind
    print("onpick scatter:", ind, np.take(x, ind), np.take(y, ind))

    # ----------- Changed -----------
    # Loop through each point index found by the event
    for i in ind:
        # Append each point to the lists
        # Note that this changes the lists, but does not reassign them
        diy_pick_x.append(np.take(x, i))
        diy_pick_y.append(np.take(y, i))

    a = diy_pick_x
    print(diy_pick_x)
    print(diy_pick_y)

fig.canvas.mpl_connect("pick_event", onpick)
plt.show() # <----- Changed

diy_pick_x = np.array(diy_pick_x) # <----- Changed
diy_pick_y = np.array(diy_pick_y) # <----- Changed

print(diy_pick_x) # <----- Changed
Mandias
  • 742
  • 5
  • 17
  • This new code does not change the result, I still have the same problem with python 3.7 – s.a Jul 02 '22 at 20:38
  • Have you tried running this code as a file like "testing.py" using the system terminal and the command: "python3 testing.py"? I am just checking since Spyder uses IPython as its "terminal", which is not the same thing. – Mandias Jul 03 '22 at 00:33
  • Thanks for following up! But I do not know how to access to variables after running in the terminal. – s.a Jul 06 '22 at 20:36
  • As long as the data is printing as expected in the system terminal, then we know that IPython is the problem, not your Python version. I am not familiar with how IPython works, so all I can suggest is that you use regular print commands to view variables and practice doing everything automatically in scripts instead of multiple terminal commands. – Mandias Jul 07 '22 at 00:26