简体   繁体   English

如何构建我自己的 Python 信号处理模块?

[英]How to structure my own Python signal processing module?

I want to take my Python (currently Version 3.9.7) programming skills to a next level.我想将我的 Python(当前版本 3.9.7)编程技能提升到一个新的水平。 Up to now I just wrote some small scripts for myself, that no one hat to review or reuse.到目前为止,我只是为自己写了一些小脚本,没有人可以查看或重复使用。 Now, I want to write code that can be considered as "clean" and can be reused by others.现在,我想编写可以被认为是“干净”并且可以被其他人重用的代码。 For this purpose, I am writing my own signal processing module with which I can generate high- and lowpassfilters in order to filter signals.为此,我正在编写自己的信号处理模块,我可以使用它生成高通和低通滤波器以过滤信号。 I have no experience with structuring packages / modules, so I have some questions regarding code structure.我没有构建包/模块的经验,所以我对代码结构有一些疑问。

Up to now, I have a class sim_lowpass:到目前为止,我有一个类 sim_lowpass:

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 22 10:37:19 2022

@author: ilja
"""

from matplotlib import pyplot as plt
import math


class sim_lowpass:
    """ Lowpass Simulation Class """
    
    def __init__(self, cutoff: int, order: int, fs: int) -> None:
        self.fs = fs
        self.nyq = int(0.5 * fs)
        self.cutoff = cutoff
        self.order = order
    
    
    def _transfer_func(self,f: float) -> float:
        """ Transfer function in the z-domain """
        
        if self.order == 1:
            return 1/(1+(f/(2*math.pi*self.cutoff)))
    
        
    def transfer_func(self) -> list[float]:
        """ Transfer function in the z-domain """
        
        if self.order == 1:
            # f = np.linspace(self.df, self.nyq, self.N/2)
            f = list(range(int(self.nyq)))
            return [self._transfer_func(i) for i in f]
    
    
    def propagate(self, x_hat):
        filtered = [i*j for i,j in zip(x_hat, self.impulse_response())]
        return filtered
    
    
    def bode_plot(self, tr_func: list[float]) -> None:
        fig, (ax1, ax2) = plt.subplots(2, 1, constrained_layout=True, 
                                       figsize = (8,5))
        ax1.plot(list(range(self.nyq)), tr_func)
        #ax1.set_title('Magnitude')
        ax1.set_xscale('log')
        ax1.set_yscale('log')
        ax1.set_ylabel('Magnitude (dB)')
        ax1.grid(True)
        # ax2.plot(list(range(self.nyq)), tr_func) # TODO
        # ax2.set_title('Phase')
        ax2.set_xscale('log')
        ax2.set_yscale('log')
        ax2.set_xlabel('Frequency (Hz)')
        ax2.set_ylabel('Phase (deg)')
        ax2.grid(True)
        
        fig.suptitle('Bode Plot', fontsize=16)
    

def main() -> None:
    # define filter params
    cutoff = 100
    order = 1
    fs = 4e6
    
    # create filter
    lp = sim_lowpass(cutoff, order, fs)
    tf = lp.transfer_func()
    lp.bode_plot(tf)    


if __name__ == '__main__':
    main()

Questions:问题:

  • First of all: Is the code up to now well structured (in terms of scalability, testability, ... what else is there?)首先:到目前为止的代码结构是否良好(在可扩展性、可测试性方面……还有什么?)

  • Second: Now I want to create the class sim_lowpass.第二:现在我想创建类 sim_lowpass。 How do I continue without copy-pasting the parts I can reuse from the highpass class?如果不复制粘贴可以从 highpass 类中重复使用的部分,我该如何继续?

  • Third: Where do I place this file (and what would be a meaningful name) inside the package hierarchy?第三:在包层次结构中,我在哪里放置这个文件(以及什么是有意义的名称)?

  • Last but not least: Any other tips for improvement?最后但并非最不重要的一点:还有其他改进技巧吗?

I usually get inspiration for code-structure from real projects.我通常从实际项目中获得代码结构的灵感。 For example, since you are using matplotlib, their github could be a place to start: https://github.com/matplotlib/matplotlib/tree/main/lib/matplotlib例如,由于您使用的是 matplotlib,他们的 github 可能是一个开始的地方: https ://github.com/matplotlib/matplotlib/tree/main/lib/matplotlib

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM