pywt icon indicating copy to clipboard operation
pywt copied to clipboard

Inference of trim_approx in iswt

Open ChrisMyers opened this issue 6 years ago • 2 comments

Regarding the recent introduction of the trim_approx option to swt, it appears that the inverse transform iswt attempts to infer whether or not swt was called with trim_approx=False via the following code:

# If swt was called with trim_approx=False, first element is a tuple
trim_approx = not isinstance(coeffs[0], (tuple, list))

The problem with this is that it assumes that the type of the coeffs produced by swt has not been modified in some unexpected way. In my case, I have previously written code to convert the coeffs returned by swt ( [(cAn, cDn), ..., (cA2, cD2), (cA1, cD1)] ) to a numpy array so that I can manipulate them more easily. Unfortunately, with that type conversion having been carried out, the code above infers that swt was called with trim_approx=True when in fact it was not. (And in the wake of this erroneous inference, all sorts of things break downstream.) Prior to the introduction of the trim_approx option, iswt was quite content dealing with my numpy array of coeffs.

Is there some other way to more robustly infer trim_approx (e.g., based on the length of coeffs and the number of levels used)?

Alternatively, would you consider adding a trim_approx option to iswt as well so that this inference can be overridden? Presumably you might want to keep the inference for the typical case where coeffs has not been modified, in which case you might need to distinguish among trim_approx being True, False, and something like None (with the last one triggering the inference).

ChrisMyers avatar Oct 31 '19 14:10 ChrisMyers

Thanks @ChrisMyers.

To clarify, you were previously calling np.asarray(coeffs) where coeffs is the output of pywt.swt? I am not sure we intended to support that case, and did not have any test cases for it in our test suite. That said, I am not opposed to working to find a solution here.

It seems that calling np.asarray will give an ndarray of shape (levels, 2) + data.shape when trim_approx = False or shape of (levels + 1,) + data.shape when trim_approx = True. Given that data does not strictly have to be 1D, I don't think we can safely infer from array dimensions whether trim_approx had been called.

grlee77 avatar Oct 31 '19 17:10 grlee77

I am thinking the following autodetection would also work for your case and can replace the current check in the code:

trim_approx = np.isscalar(tuple(coeffs[0])[0])

In the case trim_approx = True, tuple(coeffs[0]) will give a 2-tuple of ndarrays, but for False it will give just a tuple of floats corresponding to approximation coefficients. So by checking the first element of tuple(coeffs[0]) we can differentiate between the two.

grlee77 avatar Oct 31 '19 17:10 grlee77