chipmuenk/pyfda

Crash when designing differentiator with F_PB = 0.01

nyanpasu64 opened this issue · 6 comments

When I design a differentiator filter but set F_PB = 0.01, the entire program crashes. At F_PB = 0.02 or 0.03, I get funny errors:

[ INFO][23:53:01.735] [input_specs.py:303] Start filter design using method
        'Equiripple.DIFFman'
[ ERROR][23:53:01.739] [filter_factory.py:245] ErrCode 99: Method 'DIFFman' of class 'Equiripple':
Array must not contain infs or NaNs

As far as I can tell, changing F_PB does not affect the filter output magnitude response.

Branch: develop 39a5827. Python 3.7 x64 on Windows 10 x64.

Yes, I can reproduce the errors. Additionally, clicking on the b,a tab crashes pyfda when the error messages above have been produced:

Traceback (most recent call last):
File "d:\daten\design\python\git\pyfda\pyfda\input_widgets\input_fixpoint_specs.py", line 112, in process_sig_rx
self.wdg_dict2ui()
File "d:\daten\design\python\git\pyfda\pyfda\input_widgets\input_fixpoint_specs.py", line 589, in wdg_dict2ui
self.fx_wdg_inst.dict2ui()
File "d:\daten\design\python\git\pyfda\pyfda\fixpoint_widgets\fir_df.py", line 218, in dict2ui
self.update_accu_settings()                 # update accumulator settings
File "d:\daten\design\python\git\pyfda\pyfda\fixpoint_widgets\fir_df.py", line 179, in update_accu_settings
A_coeff = int(np.ceil(np.log2(np.sum(np.abs(fb.fil[0]['ba'][0])))))
ValueError: cannot convert float NaN to integer

Unfortunately, I have never used differentiators myself, so this part of the code hasn't been tested with practical examples. I'm just using scipy's remez function to design the filter in

def DIFFman(self, fil_dict):
self._get_params(fil_dict)
if not self._test_N():
return -1
self.N = ceil_even(self.N) # enforce even order
self._save(fil_dict, sig.remez(self.N,[0, self.F_PB],[np.pi*fil_dict['W_PB']],
Hz = 1, type = 'differentiator', grid_density = self.grid_density))

If you have time (and know how to) you could try to achieve what you want to do with the remez function with the help of the documentation and the example at https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.remez.html

Based on your inputs, I could adapt the UI for the differentiator.

The actual error is happening most likely downstream in the fil_save() function

def fil_save(fil_dict, arg, format_in, sender, convert = True):

which converts between b,a and P,Z and SOS filter notation. I need to look into that.

Note to myself: replace deprecated option Hz = 1 by fs = 1 in remez calls.

Thanx once more for reporting but after thinking a bit about the issue I'm a bit confused: Why would you want to set F_PB to such a low value? F_PB specifies the upper frequency where the differentiator is supposed to work correctly. For normalized frequencies below 0.1 the requirements are so easy to fulfil that appearently the algorithm fails. I think I'll limit the lower value for F_PB in the UI and I'll fix the crash ocurring further downstream.

I'm new to filter design and don't know what F_PB is, lol...

I guess lack of documentation is part of the problem ... F_PB is the upper frequency of the passband which in the case of a differentiator specifies the range where the filter should approximate a differentiatior. That's the reason why you don't see any change in the frequency when varying F_PB between say 0.1 and 0.05 - in both cases the differentiator approximation works very well, the filters won't be much different.

Investigated further: For low bandwidths like F_PB = 0.02 a bunch of nans is returned which can be caught easily. When F_PB = 0.01, the python kernel crashes, M(N)WE:

from scipy.signal import remez
remez(10, [0,0.01],type='differentiator')

An issue has been opened at scipy for this.

Issue is fixed on the pyfda side by limiting the allowed argument range.