Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

argrelmin/argrelmax fail with smooth data and plateaus #6848

Closed
Chris7 opened this issue Dec 11, 2016 · 7 comments · Fixed by #8264
Closed

argrelmin/argrelmax fail with smooth data and plateaus #6848

Chris7 opened this issue Dec 11, 2016 · 7 comments · Fixed by #8264

Comments

@Chris7
Copy link

Chris7 commented Dec 11, 2016

There are certain cases that argrelmin/max will fail due to the comparator being used. For instance:

from scipy.signal import argrelmin, argrelmax
import numpy as np
x = np.array([1,2,3,3,2,1])
print(argrelmax(x))

returns (array([], dtype=int64),)

This happens because the comparator is np.greater. Should this be fixed to provide some resolution or is this the desired behavior?

@person142
Copy link
Member

Essentially the same issue as #3749.

@Chris7
Copy link
Author

Chris7 commented Dec 11, 2016

Here is some code that is one possible fix for _boolrelextrema:

def _boolrelextrema(data, comparator, axis=0, order=1, mode='clip'):
    if((int(order) != order) or (order < 1)):
        raise ValueError('Order must be an int >= 1')

    datalen = data.shape[axis]
    locs = np.arange(0, datalen)
    data = np.ma.masked_array(data, mask=np.hstack(([1], np.diff(data)))==0)
    if np.ma.is_masked(data):
        locs = locs[np.ma.getmask(data)==False]
        main = data.take(locs, axis=axis, mode=mode)
        results = np.zeros(data.shape, dtype=bool)
        for index, result in enumerate(_boolrelextrema(main, comparator, axis=axis, order=order, mode=mode)):
            results[locs[index]] = result
        return results
    else:
        locs = locs[np.ma.getmask(data)==False]
        results = np.ones(data.shape, dtype=bool)
        main = data.take(locs, axis=axis, mode=mode)
        for shift in xrange(1, order + 1):
            plus = data.take(locs + shift, axis=axis, mode=mode)
            minus = data.take(locs - shift, axis=axis, mode=mode)
            results &= comparator(main, plus)
            results &= comparator(main, minus)
            if(~results.any()):
                return results
        return results
_boolrelextrema(x, np.greater)

It makes assumptions about how you want to report the duplicates, but it's workable for me atm.

@Chris7
Copy link
Author

Chris7 commented Dec 11, 2016

Bah, sorry for the dupe @person142. Feel free to close/reference this from there if you wish.

@ilayn
Copy link
Member

ilayn commented Dec 11, 2016

@Chris7 Since it is referenced already, you can close this one yourself anyways.

@person142
Copy link
Member

The other doesn't mention argrelmax or argrelmin, so IMO it's not unreasonable to leave both open so long as they are linked (even though fixing _boolrelextrema fixes both). @Chris7 re

Here is some code that is one possible fix

any interest in turning that into a PR?

@Chris7
Copy link
Author

Chris7 commented Dec 11, 2016

I can try. I don't know how I can really translate it to the multi-dimensional case. Since what I am in effect doing is popping out the duplicates, that will quickly fail once I am working with anything > 1d.

@lagru
Copy link
Contributor

lagru commented Mar 1, 2018

There is now an alternative to _boolextrema for the 1D case: _argmaxima1d introduced in #8350. It approximates the center of flat maxima. I think that function could cover the >1D case with a few small changes as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants