<p dir="auto">I'm doing some work in filtering and having a bit of a rough time.  I went looking for some examples and I found this:</p>
<p dir="auto"><a href="http://azitech.wordpress.com/2011/03/15/designing-a-butterworth-low-pass-filter-with-scipy/" rel="nofollow">http://azitech.wordpress.com/2011/03/15/designing-a-butterworth-low-pass-filter-with-scipy/</a></p>
<p dir="auto">It looks to me like a perfectly valid set of examples, and he's even generated some example output.  It looks reasonable.</p>
<p dir="auto">So I download the code and try running it on my machine.  I see this error:<br>
/usr/lib/python2.7/dist-packages/scipy/signal/filter_design.py:288: BadCoefficients: Badly conditioned filter coefficients (numerator): the results may be meaningless<br>
"results may be meaningless", BadCoefficients)<br>
b=[  1.50249921e-18], a=[   1.           -9.78671066   43.10310124 -112.50164481  192.7084543<br>
-226.36430741  184.66074807 -103.30140929   37.92528936   -8.25143211<br>
0.80791132]</p>
<p dir="auto">And then the graph looks substantially different:<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/e5d68ccb67641b636b0981590803add906e215f04c7d285efb791c653118f4eb/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f3130343532302f313331383437352f30316630383735322d333262642d313165332d383333362d6361636463306362616334302e706e67"><img src="https://camo.githubusercontent.com/e5d68ccb67641b636b0981590803add906e215f04c7d285efb791c653118f4eb/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f3130343532302f313331383437352f30316630383735322d333262642d313165332d383333362d6361636463306362616334302e706e67" alt="output" data-canonical-src="https://f.cloud.github.com/assets/104520/1318475/01f08752-32bd-11e3-8336-cacdc0cbac40.png" style="max-width: 100%;"></a></p>
<p dir="auto">The thing that strikes me is that in the filter passbands are HUGELY different.  The example output he shows has a passband gain of 1.  My passband gain is 10^-5 so it's all attenuation.</p>
<p dir="auto">I found this ticket <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="13652418" data-permission-text="Title is private" data-url="https://github.com/scipy/scipy/issues/2140" data-hovercard-type="issue" data-hovercard-url="/scipy/scipy/issues/2140/hovercard" href="https://github.com/scipy/scipy/issues/2140">#2140</a> and it mentioned problems with the "small enough to zero out" number.  I'm running a newer version of scipy which already has the 1e-14 threshold so that doesn't seem to be the problem.</p>
<p dir="auto">This is really puzzling me.</p>
<p dir="auto">The <a href="https://github.com/scipy/scipy/blob/master/scipy/signal/filter_design.py#L593"><code class="notranslate">iirfilter()</code></a> function internally generates filter prototypes in zpk format, transforms them to tf format, and then back to zpk format:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="z, p, k = typefunc(N)
b, a = zpk2tf(z, p, k)
b, a = lp2lp(b, a, wo=warped)
b, a = bilinear(b, a, fs=fs)
return tf2zpk(b, a)"><pre class="notranslate"><code class="notranslate">z, p, k = typefunc(N)
b, a = zpk2tf(z, p, k)
b, a = lp2lp(b, a, wo=warped)
b, a = bilinear(b, a, fs=fs)
return tf2zpk(b, a)
</code></pre></div>
<p dir="auto">But conversion to tf format introduces numerical errors, causing higher-order filters to fail, even though the higher-order prototypes work fine.  It should use zpk format (or state-space format?) throughout, and these functions should be changed to accept zpk format or be replaced by ones that do.</p>
<p dir="auto">I started to implement this, but then realized it involves lots of changes to lots of functions, some of which I'm not sure the best way to do, so registering this issue in case others want to work on it, too.</p>
<p dir="auto">For instance, <a href="http://www.mathworks.com/help/signal/ref/bilinear.html" rel="nofollow">matlab's bilinear function</a> accepts tf, zpk, and ss formats, by varying the number of input parameters, which I don't think is "Pythonic" (though <code class="notranslate">lti()</code> does it).  <a href="http://docs.scipy.org/doc/scipy-dev/reference/generated/scipy.signal.bilinear.html" rel="nofollow">SciPy's bilinear function</a> accepts <code class="notranslate">b</code> and <code class="notranslate">a</code> as separate parameters, and then <code class="notranslate">fs</code>, so it can't be modified to use variable number of input variables anyway, without breaking compatibility.  A new function could be created that takes zpk, or the existing function could take a list as its first parameter instead, which could be zpk, tf, or ss, or something else.</p>
<p dir="auto">For comparison, Octave uses <a href="http://octave.sourceforge.net/signal/function/sftrans.html" rel="nofollow">sftrans</a> instead of lp2lp, and only accepts zpk format.</p>