Repository: kymatio/kymatio

Issue:
Default value for `Q`
For 2D and 3D, we have defaults for all parameters except `J` and `shape`, but `Scattering1D` also requires `Q`. Should we give a default for this? `Q=8`?


Discussion:
Will also simplify the paper somewhat, since we don't have to get into a discussion about `Q` this way.
@janden yes, `Q` could use a default. So that
`S = ScatteringXd(J, shape=(8,)*X`)
works for `X=1`, `X=2`, `X=3`.

(ultimately, even the `shape` coud disappear, but that's another story)

However, I am a little bit concerned about setting `Q=8` by default. I know that this is a popular choice and leads to state of the art results in speech, but there are many other applications that require a different `Q`. Some applications in music require `Q=12`, `Q=16`, `Q=24`. In bioacoustics, I use `Q=50`. In EEG analysis, I use `Q=2`. So it's important that the user should be aware of the need to set up `Q` according to the time-frequency localization properties of the underlying signal.

By that token, the only acceptable default value I can see for `Q` is `Q=1`, because that is consistent with 2D and 3D. If `Q` ever makes it to 2D and 3D, it's very clear that `Q=1` will be the default value in these dimensions. The theory of 1D wavelets and 1D scattering is also most developed in the `Q=1` case, and extended to other quality factors as a separate generalization, almost as an afterthought.

This issue seems trivial (because the amount of code required to solve it is very short) but it's actually very important in my opinion, as it clearly sets a direction in the way we want to steer our user base. It comes down to this: among the three complaints below, which one are the least eager to reply to?
(1) "help: how to reproduce the experiments on TIMIT?" (answer: set `Q=8`)
(2) "help: why am I getting more coefficients in 1D than in 2D if 1D does not have orientations?" (answer: `set Q=1`)
(3) "help: Scattering1D gives a runtime error: Q required. What even is Q?" (answer: it's explained in the docs)

Choosing to set `Q=1` by default leads to user complaints of type (1)
Choosing to set `Q=8` by default leads to user complains ot type (2)
Choosing to not set `Q` (status quo) leads to user complaints of type (3)

There is no free lunch in API design ...
Ok. So `Q = 1` it is.

Small issue here is that the code says it's optimized for `Q > 1` (maybe it's supposed to be `Q >= 1`). I'm not sure what this means, exactly, but it might cause problems.
Worth asking @AndreuxMath about that. Another point worth keeping track of is the `phi_bw_multiplier`. The definition of `J` changes whether `Q==1` or not, so it's worth putting some thought into this to clarify.
> Worth asking @AndreuxMath about that.

Yes. @AndreuxMath, could this pose a problem?

> Another point worth keeping track of is the `phi_bw_multiplier`. The definition of `J` changes whether `Q==1` or not, so it's worth putting some thought into this to clarify.

Where does this happen?
> Where does this happen!

I stand corrected: it's actually independent of `Q`! :)

https://github.com/kymatio/kymatio/blob/master/kymatio/scattering1d/filter_bank.py#L548
Ok.

Resolving patch:
diff --git a/kymatio/scattering1d/scattering1d.py b/kymatio/scattering1d/scattering1d.py
--- a/kymatio/scattering1d/scattering1d.py
+++ b/kymatio/scattering1d/scattering1d.py
@@ -89,7 +89,7 @@ class Scattering1D(object):
         The length of the input signals.
     Q : int >= 1
         The number of first-order wavelets per octave (second-order wavelets
-        are fixed to one wavelet per octave).
+        are fixed to one wavelet per octave). Defaults to `1`.
     max_order : int, optional
         The maximum order of scattering coefficients to compute. Must be either
         `1` or `2`. Defaults to `2`.
@@ -159,7 +159,7 @@ class Scattering1D(object):
         or collected into a dictionary. For more details, see the
         documentation for `forward()`.
     """
-    def __init__(self, J, shape, Q, max_order=2, average=True,
+    def __init__(self, J, shape, Q=1, max_order=2, average=True,
                  oversampling=0, vectorize=True):
         super(Scattering1D, self).__init__()
         # Store the parameters


Test patch: