chipmuenk / pyfda Goto Github PK
View Code? Open in Web Editor NEWPython Filter Design Analysis Tool
Home Page: http://chipmuenk.github.io/
License: MIT License
Python Filter Design Analysis Tool
Home Page: http://chipmuenk.github.io/
License: MIT License
When trying to reduce the horizontal size of the input widget area, it is either shown or hidden completely when using the splitter.
Probably individual scroll areas are needed for each input widget.
The base directory that is defined in pyfda_rc throws a warning in pyfdax.py when it doesn't exist. This might confuse users, change it to level INFO.
This also gives a message during pip installation:
Detected hard-coded path in text file bin/pyfdax
Detected hard-coded path in text file bin/pyfdax_no_term
Particularly, if somebody isn't already an expert, they will be wondering what Fxx and Axx are.
Some entry fields are not yet filtered through safe_eval() and thus potentially unsafe and / or throw errors in the console. They should also use event_filter for displaying a limiting number of digits.
Integer QLineEdits:
Float QLineEdits:
File: pyfda/hdl_generation/hdl_specs.py
Since integrating the SOS (second-order sections) from scipy.signal, the designed filter can be retrieved in SOS format from the central dict via
fb.fil[0]['sos']
Using this information to simulate and design fixpoint filters using myHDL would be a major step towards an universal fixpoint filter synthesis tool.
When the coefficient table is displayed for the first time, the columns are not labelled b and a but 1 and 2.
This would be implemented in plot_widgets/plot_impz.py.
Differentiator with minimum order selected fails - "unknown design method DIFFmin": minimum order should not be selectable
Hilbert: Target specifications shows empty subwidget
When creating a complex valued filter (e.g. by deleting a single pole), the zpk2sos algorithm throws an error message (probably also true for tf2sos).
This condition should be detected in pyfda_lib.fil_convert, and in this case fil[0]['sos'] should be set to 'None'.
When choosing e.g. npz file format, *.npz should be added automatically when the extension is missing - under Windows this works but not under Linux.
The method PlotTabWidgets.update_view is called twice when filter / filter order are changed, triggered by the signal sigFiltChanged.
The first time is triggered by select_filter.py -> load_filter_order() (filter / filter order have been edited) and the second time by filter_specs.py -> update_UI.
First of this tool looks great! thank you so much for your effort in putting this together.
I'm trying to use this to plot / design low and high pass filters though noticed that in changing the Fc value the filters are not changing. The filters always seem to be calculated using the default Fc value for the filter type. Is there a known work around for this issue? The filter order does seem to be working properly.
Add another error handler to display debug,info, error messages to user on the main display. In addition to logging errors to error log and terminal window, they will also appear on the main GUI display.
When adding / deleting poles or zeros, the gain factor k remains unchanged. This changes the overall filter gain e.g. in the passband.
File: input_widgets/input_pz.py
Method: normalizeCoeffs()
When creating a design that fulfills the specs at the corners of pass and stop band but violates them somewhere inbetween, this is not flagged in the Info tab (input_widgets/input_info.py).
The reason is that so far only the band corners are checked ...
In contrast to FIR filter design, IIR filters only can be designed with identical amplitude specs for both pass- resp. stopbands.
The UI does not allow to enter e.b. A_PB2 or A_SB2, hence, prior settings are used for displaying the specs in H(f) and the info tab.
Solution: Copy A_PB -> A_PB2 resp. A_SB -> A_SB2 in the filter design routines.
I've noticed an issue in the calculation of group delay and magnitude response when designing a highly constrained filter: Lowpass, IIR (N=10), Chebychev 2, Fc = 0.01, Asb = 60 . This issue appears to be caused by the use of the transfer function polynomials in the calculation and I have been able to correct the group delay by changing the calculation to use zero-pole values instead of the polynomials (see code below). I did some testing and it looks like the magnitude response appears to be corrected if the filter is designed in the analogue domain however this affects subsequent frequency and group delay calculations and the coefficients need to be transformed to the digital domain.
'''
add to pyfda/plot_widgets/plot_tau_g.py (line 82)
remove/comment out currently defined w and tau_g variables
'''
zz = fb.fil[0]['zpk'][0]
pp = fb.fil[0]['zpk'][1]
G = np.zeros(rc.params['N_FFT'])
w = np.arange(0,1, 1/rc.params['N_FFT']) * np.pi
for i in range(zz.shape[0]):
rz = np.abs(zz[i])
az = np.angle(zz[i])
G += (-rz*np.cos(w-az) + rz**2) / (rz**2 - 2*rz*np.cos(w-az) + 1)
for i in range(pp.shape[0]):
rp = np.abs(pp[i])
ap = np.angle(pp[i])
G -= (-rp*np.cos(w-ap) + rp**2) / (rp**2 - 2*rp*np.cos(w-ap) + 1)
tau_g = G
RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap the QObject class
This is a regression that had been fixed with PR #11 and was re-introduced by me while adding pyQt5 compatibility and hunting down another but.
As far as I understand the problem, matplotlib inherits from QObject which is ambiguous when both libraries are present on the system.
Solution: Specifiy the backend for matplotlib when it is imported for the first time:
import matplotlib
matplotlib.use("Qt5Agg")
Especially for complex P/Z and coefficients, the input fields become very wide. For low-resolution displays it would be nice to reduce the number of displayed widgets.
However, internally and when editing a field, the full resolution needs to be maintained.
This could be achieved by keeping a shadow copy.
pyfda_rc.params['FMT_ba']
and fixpoint formatspyfda_rc.params['FMT_pz']
and formatsFile: pyfda/hdl_generation/hdl_specs.py
The file name / path entered in the file dialog in the methods createHDL()
and simFixPoint()
is not passed to the actual myhdl routines, hence all resulting files are created in the default directory.
... hopefully, this is easy once the crash issue has been fixed.
pyFDA should detect at startup whether pyQt5 is available and set a corresponding global flag for doing something like
if PYQT5: from PyQt5 import QtGui from PyQt5.QtCore import pyqtSignal else: from PyQt4 import QtGui from PyQt4.QtCore import pyqtSignal
For details see http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html
Debug information should be presented more structured and detailed (input_widgets/input_info.py):
For manual filter order design algorithms, target frequency and amplitude specs should be displayed although they are not used for the design process.
They are needed though for displaying the spec limits. Currently, this doesn't work.
The root cause for this lies in the module filter_specs.py where the amp. and freq. parameters for minimum order filter design are misused as target specs. This has to be fixed by adding 'targ' parameters in the filter specifications of all filter modules and using them for the spec limits.
Selecting different sets of icons depending on the theme could be achieved by:
<qresource prefix="/images/icons/dark">
<file alias="quantize.svg">quantize.svg</file>
</qresource>
This would require compiling to e.g. qrc_resources_dark.py
and qrc_resources_light.py
and make a conditional import.
The following style sheet could be used or modified:
https://github.com/ColinDuquesnoy/QDarkStyleSheet
Each time the design method, response type or filter order (min/man) is changed, the specs for frequency, amplitude, filter order and target amp/frequency are updated, firing a local sigSpecsChanged signal in each subwidget.
These signals are connected to input_widgets.input_specs.sigSpecsChanged which is connected
to input_widgets.input_tab_widgets.sigSpecsChanged.
Finally, in pyfdax.py, the signal triggers pltTabWidgets.update_view, updating the subplots four times causing unneccessary delay.
ToDo: make creation of sigSpecsChanged in the subwidgets more intelligent (was the update caused by changing individual specs or by reloading all?)
The QTableWidget for viewing and editing pole/zeros is still missing.
It would be very helpful to create a design report for a generated filter (PDF) containing relevant plots and tables.
A very promising approach is described in
where HTML to PDF conversion is achieved with pdfkit, HTML generation is controlled with jinja2 (needs to be installed).
As an alterative, PDF could be generated directly using fpdf:
https://stackoverflow.com/questions/47195075/insert-base64-image-to-pdf-using-pyfpdf
Display P/Z in various formats using itemDelegates
similar to filter_coeffs.py
Sort the P/Z according to:
More options in the editor
Interactive Editing
When a dedicated signal-slot connection between the editor and the plot window has been established, it should be easy to:
Providing interactive options as explained in https://stackoverflow.com/questions/29277080/efficient-matplotlib-redrawing allows to
For some filter designs, dynamic subwidgets with text entries, combo boxes etc. are created (e.g. grid_density for equiripple designs).
Changing these subwidgets does not trigger the signal sigSpecsChanged.
Reminder: Check whether signals are properly disconnected when reloading filters !
Shrink the status window to a smaller size and place it under the plot widget tab.
Hello. Thank you for this useful tool. I installed it on my laptop with Windows 10, which is set to 150% scaling, 144 dpi. Unfortunately, everything was so tiny, to the point of being unreadable.
A possible reason is that you specify font sizes in absolute pixels (12px) which probably does not allow scaling on high dpi displays. I've changed font sizes to points, by replacing in pyfda_rc.py, 12px
with 10pt
(three occurrences). This way, the font scales well and the interface looks good both on standard display and on the high dpi one.
The second problem was that the left pane was way too narrow, most of the list box items were replaced with ellipsis. For my own purposes, I changed the pane width (pyfdax.py, line 97) to setMaximumWidth(420)
and now it looks good on my display. Maybe this value should be set automatically based on screen width. Maybe this line is not even necessary.
Edit: I've just checked this on my laptop: removing this line gives a nice looking layout.
An another thing: tabs labels were not fitting in the tabs. You specify the minimum width of tab as 10ex
(pdyfa_rc.py, line 165). ex is the height unit, width should be specified with em because it makes sense. Changing this to min-width: 5em;
gave the result that looks very nice on my screen.
Please consider making these changes in your code.
When closing the application by closing the window or by clicking the "Quit" button, the python kernel crashes (Windows 7, 64 bit). I don't know whether the same happens under other OS's.
In some cases, default corner frequencies e.g. for pass- and stop band are identical. This means, something goes wrong between reading frequency specs from the global filter dict and displaying / storing them back to the filter dict. Could be related to issue #6.
How to reproduce the issue:
379: self.fo = foList[0] # use first list entry from filterTree
TypeError: 'dict_keys' object does not support indexing
Here, a minimum order bandpass is not contained in the filter dict. Consequently, it should not be selectable at all. But it is and it produces the error above.
... as the title says, forgotten to rename it at some point.
Forgot to relabel the tablewidget header in input_pz._clear_table()
Shrink name of new elliptic zero phase filter in pullDown menu.
Improve name of file_io pullDown menu for custom text file output
When a filter is designed manually by saving P/Z or b,a, the filter design method changes to "manual" but the display of the widgets is not updated.
This would require triggering FilterSpecs.update_UI()
.
The QClipboard widget is an elegant way for importing (e.g. coefficients, P/Z, ...) and exporting (e.g. screenshots) data - this would enhance interfaces and functionality.
See e.g. http://python.6.x6.nabble.com/Paste-entire-column-into-QTableView-from-Excel-td5016995.html
Clipboard functionality has been started as qcopy_to_clipboard()
and qcopy_from_clipboard()
in the library pyfda_qt.lib
: The following steps are required / are working already:
qcopy_to_clipboard()
with all cells as floatqcopy_to_clipboard()
with selected cells in current format: second column (empty) is always copied as empty string. When only some cells are selected, number, order and content are not correct.qcopy_from_clipboard()
as float or in selected formatWanted to install the new version. Used the described command "python setup.py -install" form the mainpage. If you look in the setup help using "python setup.py --help", the install command is "python setup.py install". Without the "-" which works perfectly fine :)
Currently, all error and warning messages generated within the filter design routines are printed to the console (where you'll probably miss them).
A pop-up window or a text field in the GUI should display them instead (or additionally).
Certain choices caused these errors:
[ ERROR] [pyfda.pyfda_lib:1147] could not broadcast input array from shape (0) into shape (2)
[ ERROR] [pyfda.filter_factory:216] Err. Code 18:
Error calling method 'BPman' of class 'Butter':
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
[WARNING] [pyfda.input_widgets.filter_specs:286] start_design_filt:
Attribute not found.
Unknown design method.
But it is hard to tell what's wrong from messages.
Screen looks like this:
In some cases it is not possible to design a filter although the displayed filter specifications seem to be o.k. It seems that the corner frequencies are passed in the wrong order to the actual filter design routine.
This bug occurs from time to time when changing the response type (e.g. from bandpass to bandstop).
Most likely, the bug is in input_widgets/input_freq_specs.py, input_specs.py or input_targ_specs.py.
Currently, it installs conf files into the python package directory:
/usr/local/lib/python2.7/site-packages/pyfda/pyfda_log.conf
/usr/local/lib/python2.7/site-packages/pyfda/pyfda_log_debug.conf
Then the app fails:
IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/site-packages/pyfda/pyfda.log'
because this is a wrong location for the log file.
Add new IIR non-causal elliptical filter. This creates an elliptic filter with the square root of the Amplitude specs, then later the code will square the filter coefficients to create a filter with zero phase that could be applied to signal data that has been stored to a file. Applying these filter coefficients is not done in time order, so the input signal data would need to have been stored.
Update displays to show correct Frequency response, phase response, poles/zeros, group delay and impulse response for the new elliptic filter.
The active plot tab is redrawn when the size of the canvas is changed via an event filter in plotTabWidgets that calls the redraw routines of all plot widgets after a delay of 500 ms.
However, the hidden plot tabs are not affected by this, requiring a manual redraw (the brush icon).
This could be solved by only redrawing the active tab window upon resize and redrawing the other tabs when they become active.
Horizontal and vertical stretches are not removed when not needed, creating layout faults
... e.g. from 0 ... f_S/2 to 0 ... f_S and back. The graph is displayed correctly but the axis stays the same.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.