2

I wonder if anyone could help me with this problem in the application of the matplotlib widgets:

I have to work with the spectra of HII galaxies (these are simply a flat plots with some sudden peaks whose location is known to us). I need to "confirm" the location of these lines (you could say the thickness of the peaks on the plot) and determine the continuum level (this means the average y coordinate of the plot at the left and right regions of the peak). This is a simple task but given the number of plots and the number of lines in each plot I would like to use a short python code to simplify the process and avoid me missing some of the peaks.

I have watched the lectures of John Hunter on youtube and I believe I will be more than happy with the default widgets to use as my GUI, particularly the spanselector, press event and cursor event.

My problem is that I am not sure which is the right way to work with several widgets affecting the same graph: Currently my code opens a given spectrum and starts to display a fraction of the plot where I know my first line should be. Then it should continue by displaying the next line. At each loop it should perform something like this: (It is a copy from the spanselector example in matplotlib library adapted for this example)

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector

def onselectPeak(xmin, xmax):
        indmin, indmax = np.searchsorted(x, (xmin, xmax))
        indmax = min(len(x)-1, indmax)
        print "Xmin " + str(indmin) + " at index " + str(indmin)
        print "Xmax " + str(indmax) + " at index " + str(indmax)
        ax.fill_between(x[indmin:indmax], -1.0, y[indmin:indmax],facecolor='Red',alpha=0.5)

def onselectLeftContinuum(xmin, xmax):
        indmin, indmax = np.searchsorted(x, (xmin, xmax))
        indmax = min(len(x)-1, indmax)      
        print "Leftmin " + str(indmin) + " at index " + str(indmin)
        print "Leftmax " + str(indmax) + " at index " + str(indmax)
        ax.fill_between(x[indmin:indmax], -1.0, y[indmin:indmax],facecolor='Blue',alpha=0.5)

def onselectRightContinuum(xmin, xmax):
        indmin, indmax = np.searchsorted(x, (xmin, xmax))
        indmax = min(len(x)-1, indmax)
        print "Xmin " + str(indmin) + " at index " + str(indmin)
        print "Xmax " + str(indmax) + " at index " + str(indmax)
        ax.fill_between(x[indmin:indmax], -1.0, y[indmin:indmax],facecolor='Blue',alpha=0.5)       

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111, axisbg='#FFFFCC')

x = np.arange(0.0, 10.0, 1.0)
y = [0.0,0.0,0.0,0.0,5.0,0.0,0.0,0.0,0.0,0.0,]

ax.plot(x, y, '-')
ax.set_ylim([-1.0,6.0])

ax.set_title('Press left mouse button and drag Line region')
span = SpanSelector(ax, onselectPeak, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='red') )

ax.set_title('Press left mouse button and drag left region of the continuum')
span = SpanSelector(ax, onselectLeftContinuum, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='blue') )

ax.set_title('Press left mouse button and drag right region of the continuum')
span = SpanSelector(ax, onselectRightContinuum, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='blue') )

plt.show()

print "Task Completed"

To start there are two problems with this code:

  1. The plot jumps to the final span selection, ignoring the two previous
  2. The code does not stop. In all the examples of spanselector I have found, the codes keep running... I cannot find a way to stop them so I can continue with a loop...
  3. Finally, (but less important) the modifications of each area fill are not "remembered" well by the plot after each region selection

My first question is how to avoid these problems... The additional doubts I have are:

  • A) I think I could make this work by showing and closing the graphs before each span selector... but that will break my work flow...
  • B) Could I manage this with key events? How? Should it be a single key to move forward in the code? our should it be a single code for each widget I want to apply?
  • C) Would you please advice me any tutorial on matplotlib to learn how to manage the code flow with key events?

If you managed to read this very long question thanks a lot!

---EDIT

I have been working on this problem for the last week and I have finally started to understand how it should work:

1) Events and plt.show must be running all the time. Indeed, the latter is designed to be set implemented at the end of the code. The events call should be just before

2) To change the data on your figures you can use a key event. This post illustrates the right way to do it and it includes a class for it

Using events with matplotlib in a for loop

3) The problem with this structure is that your code must be fragmented in different methods. You need to make sure to define your variables in the main code so they can be imported across different methods (I am still struggling with this... I will post an example code when I am done)

One additional question: When I try to run the cursor widget with the spanselector widget the widgets glitches in a rather... painful way to the eye way... Is there anyway to avoid this? I have been playing with the cursor useblit widget but no luck

4

0 回答 0