pennmem/ptsa

Simplify output of MorletWaveletFilter

Closed this issue · 4 comments

Right now the docstring says:

    output: str
        One of: 'power', 'phase', 'both', 'complex' (default: 'both')

where both means power and phase are returned. The complex option is confusing and maybe not necessary. It could make better sense to change this parameter to be 3 boolean parameters:

... return_power=True, return_phase=True, return_complex=False...

and then only include the results marked as True in the output.

@ctw, @leondavis1: thoughts?

This makes it more complicated:

https://github.com/pennmem/ptsa_new/blob/98be3e6d657ff40ddc4b78a1fd5f4c57632bd1b5/ptsa/data/filters/morlet.py#L92-L99

In other words, the underlying C++ code would have to be changed to allow these to all be set independently.

The "complex" option is useful for connectivity analyses, where it can be convenient to manipulate the complex time series. The intent is for the complex-valued result and the real-values results to be mutually exclusive.

Using Boolean parameters seems more Pythonic than having a magic string parameter. I don't think you need to change the C++ code; you just need slightly more complex logic to translate between the Boolean parameters and the C++ enums, something like:

if return_complex:
    mt.set_output_type(morlet.COMPLEX)
elif return_power and return_phase:
    mt.set_output_type(morlet.BOTH)
else:
    mt.set_output_type(morlet.PHASE if return_phase else morlet.POWER)

I propose the following change:

Get rid of the options of power/phase only and switch to returning either power and phase OR complex values. Additionally, in the real-valued case, return a namedtuple to not break backwards compatibility:

filter = MorletWaveletFilter(ts, freqs, return_complex=False)
out = filter.filter()
print(out.power)
print(out.phase)

# - OR -

power, phase = filter.filter()

# - OR -

filter = MorletWaveletFilter(ts, freqs, return_complex=True)
complex = filter.filter()

New proposal:

Since all other filters return a TimeSeries, MorletWaveletFilter should as well. Then we can make the constructor look more like:

filter = MorletWaveletFilter(ts, freqs, output=['power', 'phase'])

and the result is a TimeSeries with both power and phase dimensions.